зеркало из https://github.com/github/ruby.git
eval_intern.h: refine stack overflow detection
* eval_intern.h (TH_PUSH_TAG, TH_EXEC_TAG): refine stack overflow detection. chain local tag after setjmp() successed on it, because calling setjmp() also can overflow the stack. [ruby-dev:47804] [Bug #9109] * vm_eval.c (rb_catch_obj): now th->tag points previous tag until TH_EXEC_TAG(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43707 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
53953eee7c
Коммит
340390093b
10
ChangeLog
10
ChangeLog
|
@ -1,4 +1,12 @@
|
||||||
Mon Nov 18 22:47:11 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Mon Nov 18 22:47:54 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* eval_intern.h (TH_PUSH_TAG, TH_EXEC_TAG): refine stack overflow
|
||||||
|
detection. chain local tag after setjmp() successed on it, because
|
||||||
|
calling setjmp() also can overflow the stack.
|
||||||
|
[ruby-dev:47804] [Bug #9109]
|
||||||
|
|
||||||
|
* vm_eval.c (rb_catch_obj): now th->tag points previous tag until
|
||||||
|
TH_EXEC_TAG().
|
||||||
|
|
||||||
* thread_pthread.c (ruby_init_stack): set stack_start properly by
|
* thread_pthread.c (ruby_init_stack): set stack_start properly by
|
||||||
get_main_stack() if possible.
|
get_main_stack() if possible.
|
||||||
|
|
|
@ -95,8 +95,7 @@ extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval
|
||||||
rb_thread_t * const _th = (th); \
|
rb_thread_t * const _th = (th); \
|
||||||
struct rb_vm_tag _tag; \
|
struct rb_vm_tag _tag; \
|
||||||
_tag.tag = 0; \
|
_tag.tag = 0; \
|
||||||
_tag.prev = _th->tag; \
|
_tag.prev = _th->tag;
|
||||||
_th->tag = &_tag;
|
|
||||||
|
|
||||||
#define TH_POP_TAG() \
|
#define TH_POP_TAG() \
|
||||||
_th->tag = _tag.prev; \
|
_th->tag = _tag.prev; \
|
||||||
|
@ -129,7 +128,7 @@ rb_threadptr_tag_jump(rb_thread_t *th, int st)
|
||||||
[ISO/IEC 9899:1999] 7.13.1.1
|
[ISO/IEC 9899:1999] 7.13.1.1
|
||||||
*/
|
*/
|
||||||
#define TH_EXEC_TAG() \
|
#define TH_EXEC_TAG() \
|
||||||
(ruby_setjmp(_th->tag->buf) ? rb_threadptr_tag_state(_th) : 0)
|
(ruby_setjmp(_tag.buf) ? rb_threadptr_tag_state(_th) : (_th->tag = &_tag, 0))
|
||||||
|
|
||||||
#define EXEC_TAG() \
|
#define EXEC_TAG() \
|
||||||
TH_EXEC_TAG()
|
TH_EXEC_TAG()
|
||||||
|
|
|
@ -477,6 +477,14 @@ end.join
|
||||||
assert_raise(SystemStackError){m}
|
assert_raise(SystemStackError){m}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_machine_stackoverflow
|
||||||
|
bug9109 = '[ruby-dev:47804] [Bug #9109]'
|
||||||
|
assert_separately([], <<-SRC)
|
||||||
|
h = {a: ->{h[:a].call}}
|
||||||
|
assert_raise(SystemStackError, #{bug9109.dump}) {h[:a].call}
|
||||||
|
SRC
|
||||||
|
end
|
||||||
|
|
||||||
def test_cause
|
def test_cause
|
||||||
msg = "[Feature #8257]"
|
msg = "[Feature #8257]"
|
||||||
cause = nil
|
cause = nil
|
||||||
|
|
|
@ -1823,7 +1823,7 @@ rb_catch_obj(VALUE t, VALUE (*func)(), VALUE data)
|
||||||
|
|
||||||
TH_PUSH_TAG(th);
|
TH_PUSH_TAG(th);
|
||||||
|
|
||||||
th->tag->tag = tag;
|
_tag.tag = tag;
|
||||||
|
|
||||||
if ((state = TH_EXEC_TAG()) == 0) {
|
if ((state = TH_EXEC_TAG()) == 0) {
|
||||||
/* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
|
/* call with argc=1, argv = [tag], block = Qnil to insure compatibility */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче