> Le Wed, Aug 01, 2018 at 06:42:30PM +0200, Bram Moolenaar a écrit :
> >
> >Patch 8.1.0232
> >Problem: Ruby error does not include backtrace.
> >Solution: Add an error backtrace. (Masataka Pocke Kuwabara, closes #3267)
> >Files: src/if_ruby.c
>
> [...]
>
> >+ bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0);
> >+ for (i = 0; i < RARRAY_LEN(bt); i++)
> >+ msg_attr((char_u *)RSTRING_PTR(RARRAY_AREF(bt, i)), attr);
>
> It is safe to use RARRAY_AREF() here?
>
> A quick (and not testted...) patch to illustrate the problem.
>
>
> diff --git a/src/if_ruby.c b/src/if_ruby.c
> --- a/src/if_ruby.c
> +++ b/src/if_ruby.c
> @@ -946,7 +946,7 @@ static int ensure_ruby_initialized(void)
> return ruby_initialized;
> }
>
> -static void error_print(int state)
> +static VALUE _error_print(VALUE _state)
> {
> #ifndef DYNAMIC_RUBY
> #if !(defined(RUBY_VERSION) && RUBY_VERSION >= 19) \
> @@ -961,6 +961,7 @@ static void error_print(int state)
> int attr;
> char buff[BUFSIZ];
> long i;
> + int state = (int)_state;
>
> #define TAG_RETURN 0x1
> #define TAG_BREAK 0x2
> @@ -1018,12 +1019,22 @@ static void error_print(int state)
> attr = syn_name2attr((char_u *)"Error");
> # ifdef RUBY21_OR_LATER
> bt = rb_funcallv(error, rb_intern("backtrace"), 0, 0);
> + Check_Type(bt, T_ARRAY); /* Can be nil in real world ? */
> for (i = 0; i < RARRAY_LEN(bt); i++)
> - msg_attr((char_u *)RSTRING_PTR(RARRAY_AREF(bt, i)), attr);
> + {
> + VALUE p = RARRAY_AREF(bt, i);
> + Check_Type(p, T_STRING);
> + msg_attr((char_u *)RSTRING_PTR(p), attr);
> + }
> # else
> bt = rb_funcall2(error, rb_intern("backtrace"), 0, 0);
> + Check_Type(bt, T_ARRAY);
> for (i = 0; i < RARRAY_LEN(bt); i++)
> - msg_attr((char_u *)RSTRING_PTR(RARRAY_PTR(bt)[i]), attr);
> + {
> + VALUE p = RARRAY_PTR(bt)[i];
> + Check_Type(p, T_STRING);
> + msg_attr((char_u *)RSTRING_PTR(p), attr);
> + }
> # endif
> break;
> default:
> @@ -1031,6 +1042,15 @@ static void error_print(int state)
> EMSG(buff);
> break;
> }
> + return Qtrue;
> +}
> +
> +static void error_print(int state)
> +{
> + int curstate;
> + rb_protect(_error_print, (VALUE)state, &curstate);
> + if (curstate)
> + EMSG("Call stack not available...");
> }
>
> static VALUE vim_message(VALUE self UNUSED, VALUE str)
> diff --git a/src/testdir/test_ruby.vim b/src/testdir/test_ruby.vim
> --- a/src/testdir/test_ruby.vim
> +++ b/src/testdir/test_ruby.vim
> @@ -364,3 +364,16 @@ func Test_p()
> let messages = split(execute('message'), "\n")
> call assert_equal('"Just a test"', messages[-1])
> endfunc
> +
> +func Test_broke_exc()
> + ruby <<--ruby
> + $_ = [
> + Class.new(Exception) { def backtrace() raise 'Quoi ?' end },
> + Class.new(Exception) { def backtrace() 42 end },
> + Class.new(Exception) { def backtrace() 0..42.to_a end },
> + ]
> +--ruby
> + for i in range(2)
> + call assert_fails('ruby raise $_.pop.new', '...')
> + endfor
> +endfunc
>
> Regards.
> Damien
Thank you for your feedback, Damien!
I am the author of the patch 8.1.0232.
I agree your idea because I think we should avoid SEGV.
But I think we can use `RB_TYPE_P` instead of `Check_Type`. `RB_TYPE_P` does
not raise error, it only returns boolean. So I think it is simpler than
`Check_Type`.
> It is safe to use RARRAY_AREF() here?
I think it is safe without dirty hack by user. For example, overriding
`Exception#backtrace`.
But Ruby allows hack to user, so I agree this patch.
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.