Is rust guaranteed to detect stack overflows?

Hello, I just accidentally wrote an infinite recursive function (not a tail call). Usually, this results in getting this message:

thread '' has overflowed its stack
fatal runtime error: stack overflow

But in my program, I get a segmentation fault:

When I start it using cargo test volkertest, I get:

process didn't exit successfully: `/path/to/binary volkertest` (signal: 11, SIGSEGV: invalid memory reference

And when I run it in the vscode debugger, I get

Stop reason: signal SIGSEGV: address access protected (fault address: 0x7ffff7a29ff8)

The call stack is:

len<core::option::Option<bindgen::ir::item::Item>> (/home/volker/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/mod.rs:95)
get<core::option::Option<bindgen::ir::item::Item>> (/home/volker/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/index.rs:155)
get<core::option::Option<bindgen::ir::item::Item>,usize> (/home/volker/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/mod.rs:282)
resolve_item_fallible<bindgen::ir::context::ItemId> (/home/volker/Sync/git/rust-bindgen/src/ir/context.rs:1475)
resolve_item<bindgen::ir::context::ItemId> (/home/volker/Sync/git/rust-bindgen/src/ir/context.rs:1483)
resolve (/home/volker/Sync/git/rust-bindgen/src/ir/context.rs:2700)
is_constified_enum_module (/home/volker/Sync/git/rust-bindgen/src/ir/item.rs:964)
is_constified_enum_module (/home/volker/Sync/git/rust-bindgen/src/ir/item.rs:982)
is_constified_enum_module (/home/volker/Sync/git/rust-bindgen/src/ir/item.rs:982)
...
is_constified_enum_module (/home/volker/Sync/git/rust-bindgen/src/ir/item.rs:982)
is_constified_enum_module (/home/volker/Sync/git/rust-bindgen/src/ir/item.rs:982)
...
start_thread (@start_thread:51)

Here, someone said that:

which sounds like rust is guaranteed to print "has overflowed its stack" instead of "signal SIGSEGV", which would mean that we have a bug here. Anyone knows if that is true? Is rust GUARANTEED to ALWAYS print "has overflowed its stack" instead of segfaulting? If yes, we just found a bug.

Rust currently uses stack probes on all tier 1 platforms, and I believe that segfaulting on stack overflow on these platforms may indicate a bug in the compiler. There's at least one known bug that can cause a segfault even on platforms with stack probes.

Rust programs can also segfault on stack overflow on platforms without stack probes, including all architectures besides x86/x86_64, and also musl.

1 Like

I'm doing that on x86_64 linux.
Guess i need to write a bug report...

Do I need a minimal example or is a big cargo crate that reproduces this fine?

FYI, Rust doesn't perform tail call optimization.

LLVM does perform tail call elimination when you compile Rust code with optimizations enabled. However, unlike some languages, Rust does not guarantee this optimization. Also, since Rust implicitly runs destructors at the end of a function, it can be tricky to write Rust code that is actually tail-recursive.

5 Likes
  1. I know that.
  2. The recursive function call is not the last statement of the function.

Slightly OT, but can't you just write drop(var) to have it dropped earlier?

Small reproducing examples are nice to have but it's also totally fine to create bug reports without them.

Yes, that works. The main tricky thing is that it's hard to see at a glance whether a function is tail-recursive or not, if the function does not explicitly drop all its variables.

1 Like

The mention of tail calls implied that a tail call may guarantee no recursion, so I dropped the FYI even though it's not what you were asking about. (Even if I had known you knew, others in this forum may not.)

1 Like

Ok, I will do that tomorrow.

The bug report is here:

4 Likes

Nope. Rust is not guaranteed to detect a stack overflow as a stack overflow, it is only guaranteed to crash:
Source:

3 Likes