Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Prefer th->ec for stack base/size. #13101

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

Merged
merged 5 commits into from
Apr 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ext/-test-/stack/extconf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: false
require_relative "../auto_ext.rb"
auto_ext(inc: true)
24 changes: 24 additions & 0 deletions ext/-test-/stack/stack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "ruby.h"
#include "internal/string.h"

static VALUE
stack_alloca_overflow(VALUE self)
{
size_t i = 0;

while (1) {
// Allocate and touch memory to force actual stack usage:
volatile char *stack = alloca(1024);
stack[0] = (char)i;
stack[1023] = (char)i;
i++;
}

return Qnil;
}

void
Init_stack(VALUE klass)
{
rb_define_singleton_method(rb_cThread, "alloca_overflow", stack_alloca_overflow, 0);
}
53 changes: 53 additions & 0 deletions test/-ext-/stack/test_stack_overflow.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true
require 'test/unit'

class Test_StackOverflow < Test::Unit::TestCase
def test_proc_overflow
omit("Windows stack overflow handling is missing") if RUBY_PLATFORM =~ /mswin|win32|mingw/

assert_separately([], <<~RUBY)
# GC may try to scan the top of the stack and cause a SEGV.
GC.disable
require '-test-/stack'

assert_raise(SystemStackError) do
Thread.alloca_overflow
end
RUBY
end

def test_thread_stack_overflow
omit("Windows stack overflow handling is missing") if RUBY_PLATFORM =~ /mswin|win32|mingw/

assert_separately([], <<~RUBY)
require '-test-/stack'
GC.disable

thread = Thread.new do
Thread.current.report_on_exception = false
Thread.alloca_overflow
end

assert_raise(SystemStackError) do
thread.join
end
RUBY
end

def test_fiber_stack_overflow
omit("Windows stack overflow handling is missing") if RUBY_PLATFORM =~ /mswin|win32|mingw/

assert_separately([], <<~RUBY)
require '-test-/stack'
GC.disable

fiber = Fiber.new do
Thread.alloca_overflow
end

assert_raise(SystemStackError) do
fiber.resume
end
RUBY
end
end
12 changes: 6 additions & 6 deletions thread_pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -3149,8 +3149,12 @@ ruby_stack_overflowed_p(const rb_thread_t *th, const void *addr)
const size_t water_mark = 1024 * 1024;
STACK_GROW_DIR_DETECTION;

if (th) {
size = th->ec->machine.stack_maxsize;
base = (char *)th->ec->machine.stack_start - STACK_DIR_UPPER(0, size);
}
#ifdef STACKADDR_AVAILABLE
if (get_stack(&base, &size) == 0) {
else if (get_stack(&base, &size) == 0) {
# ifdef __APPLE__
if (pthread_equal(th->nt->thread_id, native_main_thread.id)) {
struct rlimit rlim;
Expand All @@ -3161,15 +3165,11 @@ ruby_stack_overflowed_p(const rb_thread_t *th, const void *addr)
# endif
base = (char *)base + STACK_DIR_UPPER(+size, -size);
}
else
#endif
if (th) {
size = th->ec->machine.stack_maxsize;
base = (char *)th->ec->machine.stack_start - STACK_DIR_UPPER(0, size);
}
else {
return 0;
}

size /= RUBY_STACK_SPACE_RATIO;
if (size > water_mark) size = water_mark;
if (IS_STACK_DIR_UPPER()) {
Expand Down
Loading