Bug #8680

ruby crashes when built with AddressSanitizer

Added by Ruby Guy 9 months ago. Updated 7 months ago.

[ruby-core:56155]
Status:Closed
Priority:Normal
Assignee:-
Category:core
Target version:-
ruby -v:6398f79853f73fd307f5ecd266a94644ecf625b9 Backport:1.9.3: UNKNOWN, 2.0.0: UNKNOWN

Description

ruby crashes when built with AddressSanitizer (http://clang.llvm.org/docs/AddressSanitizer.html).

To reproduce the problem, try to build latest ruby from trunk.

$ gcc --version
gcc (GCC) 4.8.1 20130603 (Red Hat 4.8.1-1)
...

$ export CFLAGS="-fsanitize=address -O2 -g"
$ export LDFLAGS="-fsanitize=address"
$ ./configure
$ make
...
processing probes in object files
rm -f probes.o

linking miniruby

==13084== ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7fffaa2c43e0 at pc 0x7f3c76db0ac2 bp 0x7fffaa2c3ee0 sp 0x7fffaa2c3ed8
READ of size 8 at 0x7fffaa2c43e0 thread T0
#0 0x7f3c76db0ac1 (/scratch/repos/ruby/miniruby+0x11eac1)
#1 0x7f3c76db0cba (/scratch/repos/ruby/miniruby+0x11ecba)
#2 0x7f3c76db2ab0 (/scratch/repos/ruby/miniruby+0x120ab0)
#3 0x7f3c76db3a8e (/scratch/repos/ruby/miniruby+0x121a8e)
#4 0x7f3c76db52ab (/scratch/repos/ruby/miniruby+0x1232ab)
#5 0x7f3c76f1a668 (/scratch/repos/ruby/miniruby+0x288668)
#6 0x7f3c76dd1d82 (/scratch/repos/ruby/miniruby+0x13fd82)
#7 0x7f3c76e50df4 (/scratch/repos/ruby/miniruby+0x1bedf4)
#8 0x7f3c76e6fb3d (/scratch/repos/ruby/miniruby+0x1ddb3d)
#9 0x7f3c7700b86b (/scratch/repos/ruby/miniruby+0x37986b)
#10 0x7f3c76e2e3a4 (/scratch/repos/ruby/miniruby+0x19c3a4)
#11 0x7f3c76efa3f0 (/scratch/repos/ruby/miniruby+0x2683f0)
#12 0x7f3c76d8a68d (/scratch/repos/ruby/miniruby+0xf868d)
#13 0x7f3c76ef9fae (/scratch/repos/ruby/miniruby+0x267fae)
#14 0x7f3c76d8c44e (/scratch/repos/ruby/miniruby+0xfa44e)
#15 0x7f3c76d8f816 (/scratch/repos/ruby/miniruby+0xfd816)
#16 0x7f3c76fc7b37 (/scratch/repos/ruby/miniruby+0x335b37)
#17 0x7f3c76fff525 (/scratch/repos/ruby/miniruby+0x36d525)
#18 0x7f3c76fd9f69 (/scratch/repos/ruby/miniruby+0x347f69)
#19 0x7f3c76fe7986 (/scratch/repos/ruby/miniruby+0x355986)
#20 0x7f3c76fec907 (/scratch/repos/ruby/miniruby+0x35a907)
#21 0x7f3c76d83de1 (/scratch/repos/ruby/miniruby+0xf1de1)
#22 0x7f3c76d88dec (/scratch/repos/ruby/miniruby+0xf6dec)
#23 0x7f3c76d0ad98 (/scratch/repos/ruby/miniruby+0x78d98)
#24 0x7f3c725a8b74 (/usr/lib64/libc-2.17.so+0x21b74)
#25 0x7f3c76d0b6d0 (/scratch/repos/ruby/miniruby+0x796d0)
Address 0x7fffaa2c43e0 is located at offset 0 in frame of T0's stack:
This frame has 1 object(s):
[32, 36) 'cr'
...
make: *** [.rbconfig.time] Error 1

Decoding the above trace gives us,

==12684== ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7fff4ec9f180 at pc 0x7ff3ce5e6ac2 bp 0x7fff4ec9ec80 sp 0x7fff4ec9ec78
READ of size 8 at 0x7fff4ec9f180 thread T0
#0 0x7ff3ce5e6ac1 in marklocationsarray /scratch/repos/ruby/gc.c:2682
#1 0x7ff3ce5e6cba in gcmarklocations /scratch/repos/ruby/gc.c:2693
#2 0x7ff3ce5e8ab0 in gcmarksbody /scratch/repos/ruby/gc.c:3419
#3 0x7ff3ce5e9a8e in gcmarks /scratch/repos/ruby/gc.c:3653
#4 0x7ff3ce5eb2ab in heap
preparefreeslot /scratch/repos/ruby/gc.c:906
#5 0x7ff3ce750668 in str
alloc /scratch/repos/ruby/string.c:384
#6 0x7ff3ce607d82 in rbiogetlinefast /scratch/repos/ruby/io.c:2902
#7 0x7ff3ce686df4 in lex
getline /scratch/repos/ruby/parse.y:5416
#8 0x7ff3ce6a5b3d in yycompile0 /scratch/repos/ruby/parse.y:5347
#9 0x7ff3ce84186b in rbsuppresstracing /scratch/repos/ruby/vmtrace.c:367
#10 0x7ff3ce6643a4 in yycompile /scratch/repos/ruby/parse.y:5379
#11 0x7ff3ce7303f0 in load
fileinternal /scratch/repos/ruby/ruby.c:1728
#12 0x7ff3ce5c068d in rb
ensure /scratch/repos/ruby/eval.c:820
#13 0x7ff3ce72ffae in loadfile /scratch/repos/ruby/ruby.c:1765
#14 0x7ff3ce5c244e in rb
loadinternal /scratch/repos/ruby/load.c:594 (discriminator 3)
#15 0x7ff3ce5c5816 in rb
requiresafe /scratch/repos/ruby/load.c:958
#16 0x7ff3ce7fdb37 in vm
callcfuncwithframe /scratch/repos/ruby/vminsnhelper.c:1493
#17 0x7ff3ce835525 in vmcallcfunc /scratch/repos/ruby/vminsnhelper.c:1583
#18 0x7ff3ce80ff69 in vm
execcore /scratch/repos/ruby/insns.def:1017
#19 0x7ff3ce81d986 in vm
exec /scratch/repos/ruby/vm.c:1198
#20 0x7ff3ce822907 in rbiseqevalmain /scratch/repos/ruby/vm.c:1448
#21 0x7ff3ce5b9de1 in ruby
execinternal /scratch/repos/ruby/eval.c:252 (discriminator 1)
#22 0x7ff3ce5bedec in ruby
exec_node /scratch/repos/ruby/eval.c:317
#23 0x7ff3ce540d98 in main /scratch/repos/ruby/main.c:36
#24 0x7ff3c9ddeb74 in ?? ??:0
#25 0x7ff3ce5416d0 in _start ??:?

...

Is this expected behaviour? Can we patch ruby to be a bit more friendly towards AddressSanitizer?

This "problem" exists in older versions too (e.g. ruby-2.0.0-p247).

0001-enable-usage-of-AddressSanitizer-in-CRuby.patch Magnifier - enable usage of AddressSanitizer in CRuby (899 Bytes) Ruby Guy, 07/31/2013 12:33 AM

0001-Enable-usage-of-AddressSanitizer-in-CRuby.patch Magnifier (1.26 KB) Ruby Guy, 09/25/2013 10:27 PM

Associated revisions

Revision 43047
Added by Nobuyoshi Nakada 7 months ago

gc.c: disable AddressSanitizer

  • gc.c (marklocationsarray): disable AddressSanitizer. based on a patch by halfie (Ruby Guy) at . [Bug #8680]

History

#1 Updated by Akira Tanaka 9 months ago

2013/7/24 halfie (Ruby Guy) assie181@gmail.com:

Bug #8680: ruby crashes when built with AddressSanitizer
https://bugs.ruby-lang.org/issues/8680

Is this expected behaviour? Can we patch ruby to be a bit more friendly towards AddressSanitizer?

Ruby uses conservertive garbage collection.
I.e. Ruby scans stack area from beginning to end, including undefined
area intentionally.
Is it related?
--
Tanaka Akira

#2 Updated by Motohiro KOSAKI 9 months ago

Does Boehm GC works on the AddressSanitizer? IOW, is this ruby specific?

#3 Updated by Yui NARUSE 9 months ago

  • Status changed from Open to Feedback

#4 Updated by Ruby Guy 9 months ago

If we are 100% sure that the GC is fine, then the following patch can be applied to make CRuby ASAN friendly.

diff --git a/gc.c b/gc.c
index caaf00c..de7815b 100644
--- a/gc.c
+++ b/gc.c
@@ -31,6 +31,12 @@
#include
#include

+#if defined(clang) || defined (GNUC)
+# define ATTRIBUTENOADDRESSSAFETYANALYSIS attribute((noaddresssafetyanalysis)) _attribute__ ((noinline))
+#else
+# define ATTRIBUTENOADDRESSSAFETYANALYSIS
+#endif
+
#ifdef HAVESYSTIMEH
#include
#endif
@@ -2674,6 +2680,7 @@ ruby
stack_check(void)
#endif
}

+ATTRIBUTENOADDRESSSAFETYANALYSIS
static void
marklocationsarray(rbobjspacet *objspace, register VALUE *x, register long n)
{

#6 Updated by Ruby Guy 7 months ago

Attaching latest patch against tip. Feedback is welcome.

#7 Updated by Nobuyoshi Nakada 7 months ago

  • % Done changed from 0 to 100
  • Status changed from Feedback to Closed

This issue was solved with changeset r43047.
Ruby, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


gc.c: disable AddressSanitizer

  • gc.c (marklocationsarray): disable AddressSanitizer. based on a patch by halfie (Ruby Guy) at . [Bug #8680]

Also available in: Atom PDF