about summary refs log tree commit diff
path: root/compiler/rustc_lint/src
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2022-12-19 21:24:09 +0100
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2022-12-19 21:24:09 +0100
commit6bb2bda23eb0ced0375ebd119454f8e95dc36db8 (patch)
tree065debed63095b384329af8030eb28c601fd24ff /compiler/rustc_lint/src
parent4653c93e4442d88bf3278067183c8fdc0be74a1f (diff)
downloadrust-6bb2bda23eb0ced0375ebd119454f8e95dc36db8.tar.gz
rust-6bb2bda23eb0ced0375ebd119454f8e95dc36db8.zip
Fix stack overflow in recursive AST walk in early lint
The src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs test case
added to verify https://github.com/rust-lang/rust/issues/74564 still
crashes with a stack overflow on s390x-ibm-linux.

Symptom is a very deep recursion in compiler/rustc_lint/src/early.rs:
    fn visit_expr(&mut self, e: &'a ast::Expr) {
        self.with_lint_attrs(e.id, &e.attrs, |cx| {
            lint_callback!(cx, check_expr, e);
            ast_visit::walk_expr(cx, e);
        })
    }
(where walk_expr recursively calls back into visit_expr).  The crash
happens at a nesting depth of over 17000 stack frames when using the
default 8 MB stack size on s390x.

This patch fixes the problem by adding a ensure_sufficient_stack
call to the with_lint_attrs routine (which also should take care
of all the other mutually recursive visitors here).

Fixes part of https://github.com/rust-lang/rust/issues/105383.
Diffstat (limited to 'compiler/rustc_lint/src')
-rw-r--r--compiler/rustc_lint/src/early.rs3
1 files changed, 2 insertions, 1 deletions
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 5f84d5c8b94..a8c32b54355 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -19,6 +19,7 @@ use crate::passes::{EarlyLintPass, EarlyLintPassObject};
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self as ast_visit, Visitor};
 use rustc_ast::{self as ast, walk_list, HasAttrs};
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_middle::ty::RegisteredTools;
 use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
 use rustc_session::Session;
@@ -71,7 +72,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
         self.inlined_check_id(id);
         debug!("early context: enter_attrs({:?})", attrs);
         lint_callback!(self, enter_lint_attrs, attrs);
-        f(self);
+        ensure_sufficient_stack(|| f(self));
         debug!("early context: exit_attrs({:?})", attrs);
         lint_callback!(self, exit_lint_attrs, attrs);
         self.context.builder.pop(push);