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

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