# \[BUG\] Fatal recycling of SystemStackErrors

**URL:** <https://rubytalk.org/t/bug-fatal-recycling-of-systemstackerrors/8654>\
**Category:** ruby-talk\
**Created:** [29 October 2003 00:02 UTC](https://rubytalk.org/t/bug-fatal-recycling-of-systemstackerrors/8654 "2003-10-29T00:02:22Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Florian\_Gross](https://avatars.discourse-cdn.com/v4/letter/f/e9a140/32.png) [@Florian\_Gross](https://rubytalk.org/u/Florian_Gross)\
**Post date:** [29 October 2003 00:02 UTC](https://rubytalk.org/t/bug-fatal-recycling-of-systemstackerrors/8654/1 "2003-10-29T00:02:22Z")

</div>

Moin!

In Ruby 1.8.0 old SystemStackErrors seem to be reused when  
there should have been raised a new one instead:

irb(main):001:0\> y = proc { y.call }; y.call rescue nil  
=\> nil  
irb(main):002:0\> eval ‘z = proc { z.call }; z.call’  
SystemStackError: (irb):1:in `irb\_binding’: stack level too deep

This can cause serious problems when you’re running multiple Threads  
with different levels of safeness, because of fatal exceptions. This  
code snippet:

2.times {  
begin  
Thread.new {  
$SAFE = 4 # error isn’t caused on lower $SAFE levels  
r = proc { r.call }; r.call # create a SystemStackError  
}.value  
rescue Exception =\> error; end  
p error  
}

produces this output for me:

nil  
#\<fatal: exception reentered\>

I’m using ruby 1.8.0 (2003-08-04) [i386-mswin32] and the errors also  
occur with linux releases of ruby 1.8.0.

I haven’t been able to run the above test code on an 1.6.8 release yet,  
so the bug might have been introduced only recently.

That fatal exception is a show stopper for me because my application is  
instantly killed by it and because weirdly I’m not able to rescue it in  
the context where it happens.

Regards,  
Florian Gross

---

<div class="post-metadata">

**Author:** ![Yukihiro\_Matsumoto2](https://avatars.discourse-cdn.com/v4/letter/y/b9e5f3/32.png) [@Yukihiro\_Matsumoto2](https://rubytalk.org/u/Yukihiro_Matsumoto2)\
**Post date:** [29 October 2003 06:32 UTC](https://rubytalk.org/t/bug-fatal-recycling-of-systemstackerrors/8654/2 "2003-10-29T06:32:28Z")

</div>

Hi,

> **···**
>
> In message “[BUG] Fatal recycling of SystemStackErrors” on 03/10/29, Florian Gross [flgr@ccan.de](mailto:flgr@ccan.de) writes:
> 
> > In Ruby 1.8.0 old SystemStackErrors seem to be reused when  
> > there should have been raised a new one instead:
> 
> Thank you for the report. I will fix this soon, but the  
> SystemStackError object will remain reused.
> 
> The SystemStackError object was reused because when the error happened  
> stack region may be too short to create new instance.
> 
> ```
> matz.
> 
> ```

---

<div class="post-metadata">

**Author:** ![Florian\_Gross](https://avatars.discourse-cdn.com/v4/letter/f/e9a140/32.png) [@Florian\_Gross](https://rubytalk.org/u/Florian_Gross)\
**Post date:** [31 October 2003 20:42 UTC](https://rubytalk.org/t/bug-fatal-recycling-of-systemstackerrors/8654/3 "2003-10-31T20:42:05Z")

</div>

Yukihiro Matsumoto wrote:

> Hi,

Moin!

> Thank you for the report. I will fix this soon, but the  
> SystemStackError object will remain reused.

First of all: Thanks for fixing this so fast! 🙂

I think your fix might introduce a new security hole in this rare case:

An attacker in a safe environment causes the first SystemStackError of  
your application to happen and rescues it into a variable. He then does  
this:

def error.inspect  
puts “Gotcha!”  
end

Later in your application code outside of the safe environment another  
SystemStackError occurs (the attacker can’t cause this which means that  
this whole condition is quite rare) and the malicious inspect-method of  
the SystemStackError is called.

I think that this can be fixed by also freezing the globally stored  
system stack error:

— old/ruby/eval.c Fri Oct 31 21:24:47 2003  
+++ new/ruby/eval.c Fri Oct 31 21:29:15 2003  
@@ -7736,6 +7736,7 @@ Init\_Proc()  
rb\_eSysStackError = rb\_define\_class(“SystemStackError”,  
rb\_eStandardError);  
sysstack\_error = rb\_exc\_new2(rb\_eSysStackError, “stack level too  
deep”);  
OBJ\_TAINT(sysstack\_error);

- OBJ\_FREEZE(sysstack\_error);  
rb\_global\_variable(&sysstack\_error);

Regards,  
Florian Gross
