> 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.

Raspunde prin e-mail lui