Skip to content

"Aborted (core dumped)" on typo in attribute #70763

New issue

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

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

Already on GitHub? # to your account

Closed
dwrensha opened this issue Apr 4, 2020 · 12 comments
Closed

"Aborted (core dumped)" on typo in attribute #70763

dwrensha opened this issue Apr 4, 2020 · 12 comments
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) C-bug Category: This is a bug. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. P-low Low priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@dwrensha
Copy link
Contributor

dwrensha commented Apr 4, 2020

rustc crashes ungracefully when given the following input (found by fuzz-rustc):

fn main() {
   let _ = || {
       #[cfg(any(target_arc+ = "arm"))]
       fn _foo() {}
   };
}
$ rustc -vV
rustc 1.44.0-nightly (74bd074ee 2020-04-03)
binary: rustc
commit-hash: 74bd074eefcf4915c73d1ab91bc90859664729e6
commit-date: 2020-04-03
host: x86_64-unknown-linux-gnu
release: 1.44.0-nightly
LLVM version: 9.0

$ rustc main.rs
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `+`
 --> main.rs:3:28
  |
3 |        #[cfg(any(target_arc+ = "arm"))]
  |                            ^ expected one of `(`, `)`, `,`, `::`, or `=`

Aborted (core dumped)
@dwrensha
Copy link
Contributor Author

dwrensha commented Apr 4, 2020

According to gdb, the abort happens in rustc_ast::mut_visit::visit_clobber::{{closure}}, as it did with #62894.

@jonas-schievink jonas-schievink added A-attributes Area: Attributes (`#[…]`, `#![…]`) C-bug Category: This is a bug. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. I-nominated T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 4, 2020
@dwrensha
Copy link
Contributor Author

dwrensha commented Apr 4, 2020

Here's a somewhat cuter test case that hits the same failure:

fn main() {
   let _ = || {
       #[cfg(any(target_arch == "arm"))]
       let _ = ();
   };
}
$ rustc main.rs
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `==`
 --> main.rs:3:30
  |
3 |        #[cfg(any(target_arch == "arm"))]
  |                              ^^ expected one of `(`, `)`, `,`, `::`, or `=`

Aborted (core dumped)

@estebank
Copy link
Contributor

estebank commented Apr 4, 2020

cc @Centril, I think you might have been around that code recently.

@Centril
Copy link
Contributor

Centril commented Apr 4, 2020

Simplified:

const _: _ = [#[cfg(ident(ident ==))] 0];

@Centril
Copy link
Contributor

Centril commented Apr 4, 2020

Backtrace:

centril@centrilnas2:~/programming/rust/rust-gamma$ rustc +gamma-stage1 foo.rs
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `==`
 --> foo.rs:1:33
  |
1 | const _: _ = [#[cfg(ident(ident == "arm"))] 0];
  |                                 ^^ expected one of `(`, `)`, `,`, `::`, or `=`

   0: rustc_ast::mut_visit::visit_clobber::{{closure}}
             at ./src/librustc_ast/mut_visit.rs:316
   1: core::result::Result<T,E>::unwrap_or_else
             at ./src/libcore/result.rs:851
      rustc_ast::mut_visit::visit_clobber
             at ./src/librustc_ast/mut_visit.rs:315
   2: <rustc_expand::expand::InvocationCollector as rustc_ast::mut_visit::MutVisitor>::visit_expr
             at src/librustc_expand/expand.rs:1171
      rustc_ast::mut_visit::noop_visit_item_kind::{{closure}}
             at ./src/librustc_ast/mut_visit.rs:887
      rustc_ast::mut_visit::visit_opt
             at ./src/librustc_ast/mut_visit.rs:341
      rustc_ast::mut_visit::noop_visit_item_kind
             at ./src/librustc_ast/mut_visit.rs:887
   3: <rustc_expand::expand::InvocationCollector as rustc_ast::mut_visit::MutVisitor>::visit_item_kind     
             at src/librustc_expand/expand.rs:1642
      rustc_ast::mut_visit::noop_flat_map_item
             at ./src/librustc_ast/mut_visit.rs:1017
   4: <rustc_expand::expand::InvocationCollector as rustc_ast::mut_visit::MutVisitor>::flat_map_item       
             at src/librustc_expand/expand.rs:1521
   5: rustc_ast::mut_visit::noop_visit_mod::{{closure}}
             at ./src/librustc_ast/mut_visit.rs:976
      <alloc::vec::Vec<T> as rustc_ast::util::map_in_place::MapInPlace<T>>::flat_map_in_place
             at ./src/librustc_ast/util/map_in_place.rs:36
   6: rustc_ast::mut_visit::noop_visit_mod
             at ./src/librustc_ast/mut_visit.rs:976
      rustc_ast::mut_visit::MutVisitor::visit_mod
             at ./src/librustc_ast/mut_visit.rs:166
      rustc_ast::mut_visit::noop_visit_item_kind
             at ./src/librustc_ast/mut_visit.rs:894
   7: <rustc_expand::expand::InvocationCollector as rustc_ast::mut_visit::MutVisitor>::visit_item_kind     
             at src/librustc_expand/expand.rs:1642
      rustc_ast::mut_visit::noop_flat_map_item
             at ./src/librustc_ast/mut_visit.rs:1017
   8: <rustc_expand::expand::InvocationCollector as rustc_ast::mut_visit::MutVisitor>::flat_map_item       
             at src/librustc_expand/expand.rs:1521
   9: rustc_expand::expand::AstFragment::mut_visit_with::{{closure}}
             at src/librustc_expand/expand.rs:121
      <smallvec::SmallVec<A> as rustc_ast::util::map_in_place::MapInPlace<T>>::flat_map_in_place
             at ./src/librustc_ast/util/map_in_place.rs:82
  10: rustc_expand::expand::AstFragment::mut_visit_with
             at src/librustc_expand/expand.rs:121
      rustc_expand::expand::MacroExpander::collect_invocations
             at src/librustc_expand/expand.rs:577
  11: rustc_expand::expand::MacroExpander::fully_expand_fragment
             at src/librustc_expand/expand.rs:396
  12: rustc_expand::expand::MacroExpander::expand_crate
             at src/librustc_expand/expand.rs:363
  13: rustc_interface::passes::configure_and_expand_inner::{{closure}}::{{closure}}
             at src/librustc_interface/passes.rs:302
      rustc_data_structures::profiling::VerboseTimingGuard::run
             at ./src/librustc_data_structures/profiling.rs:569
      rustc_session::utils::<impl rustc_session::session::Session>::time
             at ./src/librustc_session/utils.rs:9
      rustc_interface::passes::configure_and_expand_inner::{{closure}}
             at src/librustc_interface/passes.rs:302
      rustc_data_structures::profiling::VerboseTimingGuard::run
             at ./src/librustc_data_structures/profiling.rs:569
      rustc_session::utils::<impl rustc_session::session::Session>::time
             at ./src/librustc_session/utils.rs:9
  14: rustc_interface::passes::configure_and_expand_inner
             at src/librustc_interface/passes.rs:256
  15: rustc_interface::passes::configure_and_expand::{{closure}}
             at src/librustc_interface/passes.rs:115
  16: alloc::boxed::<impl core::ops::generator::Generator<R> for core::pin::Pin<alloc::boxed::Box<G>>>::resume
             at ./src/liballoc/boxed.rs:1115
      rustc_data_structures::box_region::PinnedGenerator<I,A,R>::new
             at ./src/librustc_data_structures/box_region.rs:34
  17: rustc_interface::passes::BoxedResolver::new
             at ./<::rustc_data_structures::box_region::declare_box_region_type macros>:12
      rustc_interface::passes::configure_and_expand
             at src/librustc_interface/passes.rs:112
  18: rustc_interface::queries::Queries::expansion::{{closure}}
             at src/librustc_interface/queries.rs:176
      rustc_interface::queries::Query<T>::compute
             at src/librustc_interface/queries.rs:34
      rustc_interface::queries::Queries::expansion
             at src/librustc_interface/queries.rs:172
  19: rustc_driver::run_compiler::{{closure}}::{{closure}}
             at src/librustc_driver/lib.rs:337
      rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter
             at ./src/librustc_interface/queries.rs:385
      rustc_driver::run_compiler::{{closure}}
             at src/librustc_driver/lib.rs:286
      rustc_interface::interface::run_compiler_in_existing_thread_pool
             at ./src/librustc_interface/interface.rs:199
  20: rustc_interface::interface::run_compiler::{{closure}}
             at ./src/librustc_interface/interface.rs:213
      rustc_interface::util::spawn_thread_pool::{{closure}}::{{closure}}::{{closure}}
             at ./src/librustc_interface/util.rs:154
      scoped_tls::ScopedKey<T>::set
             at /home/centril/.cargo/registry/src/github.heygears.com-1ecc6299db9ec823/scoped-tls-1.0.0/src/lib.rs:137
      rustc_interface::util::spawn_thread_pool::{{closure}}::{{closure}}
             at ./src/librustc_interface/util.rs:150
      scoped_tls::ScopedKey<T>::set
             at /home/centril/.cargo/registry/src/github.heygears.com-1ecc6299db9ec823/scoped-tls-1.0.0/src/lib.rs:137
      rustc_ast::attr::with_globals::{{closure}}
             at ./src/librustc_ast/attr/mod.rs:44
      scoped_tls::ScopedKey<T>::set
             at /home/centril/.cargo/registry/src/github.heygears.com-1ecc6299db9ec823/scoped-tls-1.0.0/src/lib.rs:137
      rustc_ast::attr::with_globals
             at ./src/librustc_ast/attr/mod.rs:44
  21: rustc_interface::util::spawn_thread_pool::{{closure}}
             at ./src/librustc_interface/util.rs:149
      rustc_interface::util::scoped_thread::{{closure}}
             at ./src/librustc_interface/util.rs:124
      std::sys_common::backtrace::__rust_begin_short_backtrace
             at ./src/libstd/sys_common/backtrace.rs:130
  22: std::thread::Builder::spawn_unchecked::{{closure}}::{{closure}}
             at ./src/libstd/thread/mod.rs:475
      <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at ./src/libstd/panic.rs:318
      std::panicking::try::do_call
             at ./src/libstd/panicking.rs:331
  23: std::panicking::try::do_try
             at src/libstd/panicking.rs:298
  24: std::panicking::try
             at ./src/libstd/panicking.rs:274
      std::panic::catch_unwind
             at ./src/libstd/panic.rs:394
      std::thread::Builder::spawn_unchecked::{{closure}}
             at ./src/libstd/thread/mod.rs:474
      core::ops::function::FnOnce::call_once{{vtable.shim}}
             at ./src/libcore/ops/function.rs:232
  25: <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once
             at ./src/liballoc/boxed.rs:1008
  26: <alloc::boxed::Box<F> as core::ops::function::FnOnce<A>>::call_once
             at ./src/liballoc/boxed.rs:1008
      std::sys_common::thread::start_thread
             at src/libstd/sys_common/thread.rs:13
  27: std::sys::unix::thread::Thread::new::thread_start
             at src/libstd/sys/unix/thread.rs:80
  28: start_thread
             at /build/glibc-KRRWSm/glibc-2.29/nptl/pthread_create.c:486
  29: __clone

Aborted (core dumped)

@Centril
Copy link
Contributor

Centril commented Apr 4, 2020

Something in the closure here is causing a panic:

impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
        self.cfg.configure_expr(expr);
        visit_clobber(expr.deref_mut(), |mut expr| {
            self.cfg.configure_expr_kind(&mut expr.kind);

            // ignore derives so they remain unused
            let (attr, after_derive) = self.classify_nonitem(&mut expr);

            if attr.is_some() {
                // Collect the invoc regardless of whether or not attributes are permitted here
                // expansion will eat the attribute so it won't error later.
                attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));

                // AstFragmentKind::Expr requires the macro to emit an expression.
                return self
                    .collect_attr(
                        attr,
                        vec![],
                        Annotatable::Expr(P(expr)),
                        AstFragmentKind::Expr,
                        after_derive,
                    )
                    .make_expr()
                    .into_inner();
            }

            if let ast::ExprKind::MacCall(mac) = expr.kind {
                self.check_attributes(&expr.attrs);
                self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
            } else {
                noop_visit_expr(&mut expr, self);
                expr
            }
        });
    }

With the definition:

/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
/// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
/// method. Abort the program if the closure panics.
//
// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
pub fn visit_clobber<T, F>(t: &mut T, f: F)
where
    F: FnOnce(T) -> T,
{
    unsafe {
        // Safe because `t` is used in a read-only fashion by `read()` before
        // being overwritten by `write()`.
        let old_t = ptr::read(t);
        let new_t =
            panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))).unwrap_or_else(|_| {
                println!("{}", std::backtrace::Backtrace::force_capture());
                process::abort()
            });
        ptr::write(t, new_t);
    }
}

The problem seems to occur in the call to noop_visit_expr(&mut expr, self);, which is a fairly useless observation.

Digging further, unsurprisingly, the panic happens in the configure! in:

    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
        let expr = configure!(self, expr);
        expr.filter_map(|mut expr| {

@Centril
Copy link
Contributor

Centril commented Apr 5, 2020

Further down the rabbit hole, we have:

pub fn in_cfg(&self, attrs: &[Attribute]) -> bool {

which calls validate_attr::parse_meta(self.sess, attr) which in turn has:

let nmis = parse_in(sess, t.clone(), "meta list", |p| p.parse_meta_seq_top())?;

which calls:

fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {

which has:

match self.parse_meta_item() {

so we will end up in:

    crate fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
        Ok(if false && self.eat(&token::Eq) {
            ast::MetaItemKind::NameValue(self.parse_unsuffixed_lit()?)
        } else if self.check(&token::OpenDelim(token::Paren)) {
            // Matches `meta_seq = ( COMMASEP(meta_item_inner) )`.
            let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?;
            ast::MetaItemKind::List(list)
        } else {
            ast::MetaItemKind::Word
        })
    }

and reach the else {.

However, this was nested, so we are in the self.parse_paren_comma_seq( call here, and so we end up in fn parse_seq_to_before_tokens<T>( which has match self.expect(t) { so we end up calling self.expect_one_of(slice::from_ref(t), &[]) which ends up in:

        } else if self.last_unexpected_token_span == Some(self.token.span) {
            FatalError.raise();
        }

and there we have our panic. Making that line not trigger removes the abort here.

@Centril
Copy link
Contributor

Centril commented Apr 5, 2020

Unfortunately, removing the FatalError.raise() in favor of Err(...) causes a bunch of knock-on errors all over the place, and to remove with_clobber we'd need to expr.clone().

@dwrensha
Copy link
Contributor Author

dwrensha commented Apr 8, 2020

According to a git bisect I just ran:
The bug was introduced in #66994, in particular at commit 9b53c5b.

@spastorino
Copy link
Member

Assigning P-low and removing nomination. This was discussed as part of pre-triage meeting in Zulip.

@spastorino spastorino added P-low Low priority and removed I-nominated labels Apr 8, 2020
@cjgillot
Copy link
Contributor

Latest stable does not crash any more, errors gracefully.

@dwrensha
Copy link
Contributor Author

dwrensha commented Aug 5, 2021

It looks to me like the inputs above still cause rustc to abort ungracefully (using the latest rustc releases).

Also, I found another example input triggering the same crash, reported in #87790.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-attributes Area: Attributes (`#[…]`, `#![…]`) C-bug Category: This is a bug. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. P-low Low priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants