Project

General

Profile

Actions

Bug #17854

closed

Crash with certain "case" expressions on FreeBSD

Added by meta@vmeta.jp (Koichiro Iwao) about 2 months ago. Updated about 1 month ago.

Status:
Closed
Priority:
Normal
Target version:
-
ruby -v:
ruby 2.7.3p183 (2021-04-05 revision 6847ee089d) [amd64-freebsd13]
[ruby-core:103759]

Description

Affected version

  • Ruby 2.6, 2.7, 3.0 compiled with clang on FressBD

No tested with other versions. Ruby compiled with GCC doesn't have this issue.

Snippet to reproduce

ruby -e 'case 1; when 2r; 3; end'

Step to reproduce

Prepare a fresh installation of FreeBSD 13. Either Ruby installed from system package or ruby-build can reproduce the issue.

# clang -v 
FreeBSD clang version 11.0.1 (git@github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)
Target: x86_64-unknown-freebsd13.0
Thread model: posix
InstalledDir: /usr/bin
[root@ruby-bug /tmp]# clang -v 
FreeBSD clang version 11.0.1 (git@github.com:llvm/llvm-project.git llvmorg-11.0.1-0-g43ff75f2c3fe)
Target: x86_64-unknown-freebsd13.0
Thread model: posix
InstalledDir: /usr/bin

System Ruby

# pkg install ruby 
# /usr/local/bin/ruby -v
# /usr/local/bin/ruby -e 'case 1; when 2r; 3; end'

Ruby installed by ruby-build

Same as Ruby installed by ruby-build.

# pkg install rbenv ruby-build
# bash
bash# eval "$(rbenv init -)"
bash# cd /tmp
bash# rbenv install 2.7.3
bash# rbenv local 2.7.3
bash# rbenv which ruby
/root/.rbenv/versions/2.7.3/bin/ruby
bash# ruby -e 'case 1; when 2r; 3; end'

Backtrace (submitted by the original reporter)

Backtrace (with a debug build):

* thread #1, name = 'ruby27', stop reason = signal SIGSEGV
    frame #0: 0x0000000801add4e8 libruby27.so.27`append_compile_error(iseq=0x000000089445a6b8, line=1125956, fmt="") at compile.c:380:47
    frame #1: 0x00007fffffffc930
  * frame #2: 0x0000000801c4d915 libruby27.so.27`rb_st_lookup [inlined] do_hash(key=36847331000, tab=0x000000086f314d40) at st.c:326:33
    frame #3: 0x0000000801c4d90b libruby27.so.27`rb_st_lookup(tab=0x000000086f314d40, key=36847331000, value=0x00007fffffffc958) at st.c:1104
    frame #4: 0x0000000801b63443 libruby27.so.27`rb_hash_lookup2 [inlined] hash_stlike_lookup(hash=36847330480, key=<unavailable>, pval=0x00007fffffffc958) at hash.c:0
    frame #5: 0x0000000801b6339a libruby27.so.27`rb_hash_lookup2(hash=36847330480, key=36847331000, def=8) at hash.c:2070
    frame #6: 0x0000000801b0640a libruby27.so.27`when_vals(iseq=0x000000089445a550, cond_seq=0x00007fffffffcb60, vals=0x0000000878b93098, l1=<unavailable>, only_special_literals=1, literals=<unavailable>) at compile.c:4322:18
    frame #7: 0x0000000801afac70 libruby27.so.27`iseq_compile_each0 at compile.c:5334:27
    frame #8: 0x0000000801afa5c1 libruby27.so.27`iseq_compile_each0(iseq=0x000000089445a550, ret=0x00007fffffffcd60, node=0x0000000878b93108, popped=0) at compile.c:7162
    frame #9: 0x0000000801b0ab71 libruby27.so.27`setup_args_core [inlined] compile_args(node=0x0000000878b93140) at compile.c:3923:13
    frame #10: 0x0000000801b0ab59 libruby27.so.27`setup_args_core(iseq=0x000000089445a550, args=0x00007fffffffcd60, argn=<unavailable>, dup_rest=<unavailable>, flag=<unavailable>, keywords=0x00007fffffffcd28) at compile.c:5049
    frame #11: 0x0000000801af4dbf libruby27.so.27`iseq_compile_each0 [inlined] compile_call(iseq=0x000000089445a550, ret=0x00007fffffffce80, node=0x0000000878b93060, type=<unavailable>, line=1, popped=0) at compile.c:7046:16
    frame #12: 0x0000000801af4ce1 libruby27.so.27`iseq_compile_each0(iseq=0x000000089445a550, ret=0x00007fffffffce80, node=0x0000000878b93060, popped=0) at compile.c:7670
    frame #13: 0x0000000801adc735 libruby27.so.27`rb_iseq_compile_node(iseq=0x000000089445a550, node=<unavailable>) at compile.c:702:6
    frame #14: 0x0000000801b85a47 libruby27.so.27`rb_iseq_new_with_opt(ast=0x000000089445a718, name=<unavailable>, path=<unavailable>, realpath=<unavailable>, first_lineno=1, parent=0x0000000819358010, type=ISEQ_TYPE_MAIN, option=0x0000000801cf1d28) at iseq.c:821:5
    frame #15: 0x0000000801b85b6d libruby27.so.27`rb_iseq_new_main(ast=<unavailable>, path=<unavailable>, realpath=<unavailable>, parent=<unavailable>) at iseq.c:787:12
    frame #16: 0x0000000801c40537 libruby27.so.27`ruby_process_options at ruby.c:1904:9
    frame #17: 0x0000000801c3f433 libruby27.so.27`ruby_process_options(argc=<unavailable>, argv=<unavailable>) at ruby.c:2413
    frame #18: 0x0000000801b3f513 libruby27.so.27`ruby_options(argc=<unavailable>, argv=<unavailable>) at eval.c:124:2
    frame #19: 0x0000000000201cca ruby27`main(argc=<unavailable>, argv=<unavailable>) at main.c:50:23
    frame #20: 0x0000000000201a70 ruby27`_start(ap=<unavailable>, cleanup=<unavailable>) at crt1.c:76:7

Patch

The following patch is provided by the original reporter but it looks too ad-hoc. If this bug is fixed in Ruby upstream, I'll apply it to FreeBSD package.

diff --git a/compile.c b/compile.c
index 1cabb8c..a954176 100644
--- a/compile.c
+++ b/compile.c
@@ -1987,7 +1987,7 @@ cdhash_cmp(VALUE val, VALUE lit)
         return rb_float_cmp(lit, val);
     }
     else {
-        UNREACHABLE_RETURN(-1);
+        return -1;
     }
 }

@@ -2005,7 +2005,7 @@ cdhash_hash(VALUE a)
       case T_FLOAT:
         return rb_dbl_long_hash(RFLOAT_VALUE(a));
       default:
-        UNREACHABLE_RETURN(0);
+        return 0;
     }
 }

See also

Downstream bug:


Files

trace.log (37.5 KB) trace.log meta@vmeta.jp (Koichiro Iwao), 05/06/2021 11:51 AM

Related issues

Related to Ruby master - Bug #17857: `when 0r` and `when 0i` do not match with `case 0`ClosedActions
Actions #1

Updated by meta@vmeta.jp (Koichiro Iwao) about 2 months ago

  • Description updated (diff)
Actions #2

Updated by meta@vmeta.jp (Koichiro Iwao) about 2 months ago

  • Description updated (diff)

Updated by mame (Yusuke Endoh) about 2 months ago

  • Assignee set to shyouhei (Shyouhei Urabe)
  • Status changed from Open to Assigned

Thank you for the detailed report.

I confirm the issue on Ubuntu by adding logging code before UNREACHABLE_RETURN(-1).

diff --git a/compile.c b/compile.c
index 1cabb8cccd..826d9c6f4a 100644
--- a/compile.c
+++ b/compile.c
@@ -1987,6 +1987,7 @@ cdhash_cmp(VALUE val, VALUE lit)
         return rb_float_cmp(lit, val);
     }
     else {
+        puts("check2");
         UNREACHABLE_RETURN(-1);
     }
 }
@@ -2005,6 +2006,7 @@ cdhash_hash(VALUE a)
       case T_FLOAT:
         return rb_dbl_long_hash(RFLOAT_VALUE(a));
       default:
+        puts("check1");
         UNREACHABLE_RETURN(0);
     }
 }
$ ./miniruby -e 'case 1; when 2r; when 2r; end'
check1
check1
check1
check2
check1
check2
check1
check1
check2
check1
check1
check2

The code in question was introduced by shyouhei (Shyouhei Urabe) at the 33c8171c65ac0f66d1c096561e253f6f068fc85c. shyouhei (Shyouhei Urabe) could you please check this out?

Updated by shyouhei (Shyouhei Urabe) about 2 months ago

Thank you for reporting! This is my bug, clang optimizer is not guilty here.

Trying to fix at: https://github.com/ruby/ruby/pull/4469

Actions #5

Updated by shyouhei (Shyouhei Urabe) about 1 month ago

  • Status changed from Assigned to Closed

Applied in changeset git|2bc293e899c9d32dcd794a73de8925c49ecf8f15.


cdhash_cmp: can take rational literals

Rational literals are those integers suffixed with r. They tend to
be a part of more complex expressions like 123/456r, but in theory
they can live alone. When such "bare" rational literals are passed to
case-when branch, we have to take care of them. Fixes [Bug #17854]

Actions #6

Updated by mame (Yusuke Endoh) about 1 month ago

  • Related to Bug #17857: `when 0r` and `when 0i` do not match with `case 0` added

Updated by meta@vmeta.jp (Koichiro Iwao) about 1 month ago

Any chances to be backported to each supported version?

Actions #8

Updated by nagachika (Tomoyuki Chikanaga) about 1 month ago

  • Backport changed from 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.6: UNKNOWN, 2.7: REQUIRED, 3.0: REQUIRED

Updated by nagachika (Tomoyuki Chikanaga) about 1 month ago

  • Backport changed from 2.6: UNKNOWN, 2.7: REQUIRED, 3.0: REQUIRED to 2.6: UNKNOWN, 2.7: REQUIRED, 3.0: DONE

ruby_3_0 31816356eee6313fe968eecd4cd3ad9ac4848819 merged revision(s) 2bc293e899c9d32dcd794a73de8925c49ecf8f15,d0e6c6e682b9ba2b0309a5177933a0628e8ef316,cc0dc67bbbe1951ff90004bc987f78545625d772,e1eff837cf12a8e813de9d4ff2db50c9b68b86b5,0ab0b86c8491d639b9ff1335ddf35e341ecd867e,6911b4bc82889860ff7da4ecf975504cdc3e5314.

Actions

Also available in: Atom PDF