From 310af2522694dceb5f22386a1a3b51446f98d54c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Wed, 31 May 2023 20:56:14 +0200 Subject: [PATCH] ruby: fix crash in display of exception backtrace with Ruby 3 (issue #1631, issue #1886) --- ChangeLog.adoc | 1 + src/plugins/ruby/weechat-ruby.c | 68 ++++++++++++++------------------- 2 files changed, 30 insertions(+), 39 deletions(-) diff --git a/ChangeLog.adoc b/ChangeLog.adoc index 05d1a85d1..3e203db91 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -100,6 +100,7 @@ Bug fixes:: * irc: remove extra space in CTCP ACTION message sent without arguments * lua: fix crash with print when the value to print is not a string (issue #1904, issue #1905) * ruby: fix crash on quit when a child process is still running (issue #1889, issue #1915) + * ruby: fix crash in display of exception backtrace with Ruby 3 (issue #1631, issue #1886) * script: remove trailing "J" (line feed char) in source of scripts displayed * spell: check buffer pointer received in info "spell_dict" * trigger: make default triggers "cmd_pass", "cmd_pass_register" and "server_pass" compatible with multiline input (issue #1935) diff --git a/src/plugins/ruby/weechat-ruby.c b/src/plugins/ruby/weechat-ruby.c index fde6d95a5..fa940ea92 100644 --- a/src/plugins/ruby/weechat-ruby.c +++ b/src/plugins/ruby/weechat-ruby.c @@ -266,24 +266,26 @@ rb_protect_funcall (VALUE recv, ID mid, int *state, int argc, VALUE *argv) int weechat_ruby_print_exception (VALUE err) { - VALUE backtrace, tmp1, tmp2, tmp3; + VALUE backtrace, message, class, class_name, tmp3; int i; int ruby_error; - char* line; - char* cline; - char* err_msg; - char* err_class; + char *line, **cline, *err_msg, *err_class; backtrace = rb_protect_funcall (err, rb_intern ("backtrace"), &ruby_error, 0, NULL); - tmp1 = rb_protect_funcall(err, rb_intern ("message"), &ruby_error, 0, NULL); - err_msg = StringValueCStr (tmp1); + message = rb_protect_funcall(err, rb_intern ("message"), &ruby_error, 0, NULL); + err_msg = StringValueCStr (message); - tmp2 = rb_protect_funcall (rb_protect_funcall (err, rb_intern ("class"), - &ruby_error, 0, NULL), - rb_intern ("name"), &ruby_error, 0, NULL); - err_class = StringValuePtr (tmp2); + err_class = NULL; + class = rb_protect_funcall (err, rb_intern ("singleton_class"), + &ruby_error, 0, NULL); + if (class != Qnil) + { + class_name = rb_protect_funcall (class, rb_intern ("to_s"), + &ruby_error, 0, NULL); + err_class = StringValuePtr (class_name); + } if (strcmp (err_class, "SyntaxError") == 0) { @@ -295,46 +297,34 @@ weechat_ruby_print_exception (VALUE err) } else { + cline = weechat_string_dyn_alloc (256); for (i = 0; i < RARRAY_LEN(backtrace); i++) { line = StringValuePtr (RARRAY_PTR(backtrace)[i]); - cline = NULL; + weechat_string_dyn_copy (cline, NULL); if (i == 0) { - cline = (char *)calloc (strlen (line) + 2 + strlen (err_msg) + - 3 + strlen (err_class) + 1, - sizeof (char)); - if (cline) + weechat_string_dyn_concat (cline, line, -1); + weechat_string_dyn_concat (cline, ": ", -1); + weechat_string_dyn_concat (cline, err_msg, -1); + if (err_class) { - strcat (cline, line); - strcat (cline, ": "); - strcat (cline, err_msg); - strcat (cline, " ("); - strcat (cline, err_class); - strcat (cline, ")"); + weechat_string_dyn_concat (cline, " (", -1); + weechat_string_dyn_concat (cline, err_class, -1); + weechat_string_dyn_concat (cline, ")", -1); } } else { - cline = (char *)calloc (strlen (line) + strlen (" from ") + 1, - sizeof (char)); - if (cline) - { - strcat (cline, " from "); - strcat (cline, line); - } + weechat_string_dyn_concat (cline, " from ", -1); + weechat_string_dyn_concat (cline, line, -1); } - if (cline) - { - weechat_printf (NULL, - weechat_gettext ("%s%s: error: %s"), - weechat_prefix ("error"), RUBY_PLUGIN_NAME, - cline); - } - - if (cline) - free (cline); + weechat_printf (NULL, + weechat_gettext ("%s%s: error: %s"), + weechat_prefix ("error"), RUBY_PLUGIN_NAME, + *cline); } + weechat_string_dyn_free (cline, 1); } return 0;