taglib-ruby icon indicating copy to clipboard operation
taglib-ruby copied to clipboard

Writing MP4 tag sometimes causes segmentation fault.

Open Ishotihadus opened this issue 2 years ago • 18 comments

TagLib::MP4::Tag#[]= sometimes fails even if the same actions often success.

irb(main):001:0> require 'taglib'
=> true
irb(main):002:0> f = TagLib::MP4::File.new('test.m4a')
=> #<TagLib::MP4::File:0x0000000104ef0dd0 @__swigtype__="_p_TagLib__MP4__File">
irb(main):003:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
=> #<TagLib::MP4::Item:0x0000000104f3b308 @__swigtype__="_p_TagLib__MP4__Item">
irb(main):004:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
=> #<TagLib::MP4::Item:0x0000000104f71980 @__swigtype__="_p_TagLib__MP4__Item">
irb(main):005:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
=> #<TagLib::MP4::Item:0x0000000104f76638 @__swigtype__="_p_TagLib__MP4__Item">
irb(main):006:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
=> #<TagLib::MP4::Item:0x0000000104f7b368 @__swigtype__="_p_TagLib__MP4__Item">
irb(main):007:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
=> #<TagLib::MP4::Item:0x0000000104f7adf0 @__swigtype__="_p_TagLib__MP4__Item">
irb(main):008:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
=> #<TagLib::MP4::Item:0x0000000104f79338 @__swigtype__="_p_TagLib__MP4__Item">
irb(main):009:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
=> #<TagLib::MP4::Item:0x0000000104f77240 @__swigtype__="_p_TagLib__MP4__Item">
irb(main):010:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
=> #<TagLib::MP4::Item:0x0000000104f75b70 @__swigtype__="_p_TagLib__MP4__Item">
irb(main):011:0> f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
(irb):11: [BUG] Segmentation fault at 0x5f6d6f72662e6d65
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin22]

-- Crash Report log information --------------------------------------------
   See Crash Report log file in one of the following locations:
     * ~/Library/Logs/DiagnosticReports
     * /Library/Logs/DiagnosticReports
   for more details.
Don't forget to include the above Crash Report log file in bug reports.

-- Control frame information -----------------------------------------------
c:0022 p:---- s:0116 e:000115 CFUNC  :[]=
c:0021 p:0018 s:0110 e:000108 EVAL   (irb):11 [FINISH]
c:0020 p:---- s:0106 e:000105 CFUNC  :eval
c:0019 p:0020 s:0098 e:000097 METHOD /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/workspace.rb:113
c:0018 p:0152 s:0091 e:000089 METHOD /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/context.rb:497
c:0017 p:0106 s:0078 e:000077 BLOCK  /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:581
c:0016 p:0024 s:0072 e:000071 METHOD /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:770
c:0015 p:0007 s:0066 e:000065 BLOCK  /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:561
c:0014 p:0123 s:0061 e:000060 BLOCK  /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/ruby-lex.rb:253 [FINISH]
c:0013 p:---- s:0057 e:000056 CFUNC  :loop
c:0012 p:0005 s:0053 e:000052 BLOCK  /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/ruby-lex.rb:235 [FINISH]
c:0011 p:---- s:0050 e:000049 CFUNC  :catch
c:0010 p:0010 s:0045 e:000044 METHOD /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/ruby-lex.rb:234
c:0009 p:0034 s:0041 E:000638 METHOD /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:560
c:0008 p:0003 s:0036 e:000035 BLOCK  /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:494 [FINISH]
c:0007 p:---- s:0033 e:000032 CFUNC  :catch
c:0006 p:0050 s:0028 E:0005e0 METHOD /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:493
c:0005 p:0069 s:0022 e:000021 METHOD /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:416
c:0004 p:0012 s:0016 e:000015 TOP    /Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/exe/irb:9 [FINISH]
c:0003 p:---- s:0013 e:000012 CFUNC  :load
c:0002 p:0078 s:0008 E:000d50 EVAL   /Users/ishotihadus/.rbenv/versions/3.2.2/bin/irb:25 [FINISH]
c:0001 p:0000 s:0003 E:001400 DUMMY  [FINISH]

-- Ruby level backtrace information ----------------------------------------
/Users/ishotihadus/.rbenv/versions/3.2.2/bin/irb:25:in `<main>'
/Users/ishotihadus/.rbenv/versions/3.2.2/bin/irb:25:in `load'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/exe/irb:9:in `<top (required)>'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:416:in `start'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:493:in `run'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:493:in `catch'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:494:in `block in run'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:560:in `eval_input'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/ruby-lex.rb:234:in `each_top_level_statement'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/ruby-lex.rb:234:in `catch'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/ruby-lex.rb:235:in `block in each_top_level_statement'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/ruby-lex.rb:235:in `loop'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/ruby-lex.rb:253:in `block (2 levels) in each_top_level_statement'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:561:in `block in eval_input'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:770:in `signal_status'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb.rb:581:in `block (2 levels) in eval_input'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/context.rb:497:in `evaluate'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/workspace.rb:113:in `evaluate'
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/lib/irb/workspace.rb:113:in `eval'
(irb):11:in `<top (required)>'
(irb):11:in `[]='

-- Machine register context ------------------------------------------------
  x0: 0x5f6d6f72662e6d65  x1: 0x000000000000009b  x2: 0x000000016eee1f90
  x3: 0x0000000000000ca1  x4: 0x0000000000000001  x5: 0x0000000000000000
  x6: 0x000060000309be70  x7: 0x00000000000008e0 x18: 0x0000000000000000
 x19: 0x000000000000009b x20: 0x00000001060bb650 x21: 0x0000000000000000
 x22: 0x000000016eee1ff8 x23: 0x5f6d6f72662e6d65 x24: 0x00000001016ed000
 x25: 0x000000013e004740 x26: 0x00000001060bb650 x27: 0x0000000000000000
 x28: 0x0000000000000000  lr: 0x00000001015e3a7c  fp: 0x000000016eee1fd0
  sp: 0x000000016eee1f80

-- C level backtrace information -------------------------------------------
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_vm_bugreport+0x9a0) [0x1016044a8]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_bug_for_fatal_signal+0x160) [0x1014405b4]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(sig_do_nothing+0x0) [0x10156dcc8]
/usr/lib/system/libsystem_platform.dylib(_sigtramp+0x38) [0x18ebc6a84]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(callable_method_entry_or_negative+0x6c) [0x1015e3a7c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_respond_to+0x50) [0x1015e5c98]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_check_funcall_default_kw+0xec) [0x1015e843c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(convert_type_with_id+0x3c) [0x1014e4990]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_convert_type_with_id+0xc0) [0x1014e48a4]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_string_value_ptr+0x4c) [0x101581a50]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/taglib-ruby-1.1.3/lib/taglib_mp4.bundle(_ZL19SWIG_Ruby_MangleStrm+0x44) [0x10641efb0]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/taglib-ruby-1.1.3/lib/taglib_mp4.bundle(_ZL26SWIG_Ruby_ConvertPtrAndOwnmPPvP14swig_type_infoiP17swig_ruby_owntype) [0x106414a58]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/taglib-ruby-1.1.3/lib/taglib_mp4.bundle(_ZL21_wrap_Tag___setitem__iPmm) [0x106419998]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_call_cfunc_with_frame+0xe8) [0x1015f884c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_exec_core+0x1fc4) [0x1015de1c4]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_vm_exec+0x82c) [0x1015efdec]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_f_eval+0x1f0) [0x1015ea758]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_call_cfunc_with_frame+0xe8) [0x1015f884c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_exec_core+0x1fc4) [0x1015de1c4]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_vm_exec+0x82c) [0x1015efdec]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(invoke_block_from_c_bh+0x3a4) [0x1015ff188]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(loop_i+0x70) [0x1015fe908]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_vrescue2+0x170) [0x10144c660]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_rescue2+0x2c) [0x10144c4c8]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_f_loop+0x48) [0x1015ec4e8]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_call_cfunc_with_frame+0xe8) [0x1015f884c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_sendish+0x488) [0x1015fabbc]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_exec_core+0x1ec4) [0x1015de0c4]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_vm_exec+0x82c) [0x1015efdec]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(invoke_block_from_c_bh+0x3a4) [0x1015ff188]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(catch_i+0x7c) [0x1015fe850]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_catch_protect+0x15c) [0x1015ebb3c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_f_catch+0x7c) [0x1015ec408]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_call_cfunc_with_frame+0xe8) [0x1015f884c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_sendish+0x488) [0x1015fabbc]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_exec_core+0x1ec4) [0x1015de0c4]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_vm_exec+0x82c) [0x1015efdec]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(invoke_block_from_c_bh+0x3a4) [0x1015ff188]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(catch_i+0x7c) [0x1015fe850]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_catch_protect+0x15c) [0x1015ebb3c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_f_catch+0x7c) [0x1015ec408]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_call_cfunc_with_frame+0xe8) [0x1015f884c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_sendish+0x488) [0x1015fabbc]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_exec_core+0x1ec4) [0x1015de0c4]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_vm_exec+0x82c) [0x1015efdec]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(load_iseq_eval+0xf8) [0x1014ac514]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_load_internal+0x84) [0x1014a97a8]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_f_load+0xb8) [0x1014aacbc]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_call_cfunc_with_frame+0xe8) [0x1015f884c]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(vm_exec_core+0x1fc4) [0x1015de1c4]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_vm_exec+0x82c) [0x1015efdec]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(rb_ec_exec_node+0x12c) [0x10144bb38]
/Users/ishotihadus/.rbenv/versions/3.2.2/lib/libruby.3.2.dylib(ruby_run_node+0x60) [0x10144b9a4]
/Users/ishotihadus/.rbenv/versions/3.2.2/bin/ruby(main+0x68) [0x100f1bf34]

Ishotihadus avatar May 06 '23 07:05 Ishotihadus

I found that this phenomenon occurs when f.tag.item_map is accessed after some tags are added. (Of course, tag[key] = item is counted as a tag addition.) As a workaround, write item_map = f.tag.item_map at first, and then use item_map.insert or item_map.fetch. Calling f.tag.item_map after inserting tags can cause a segmentation fault.

Ishotihadus avatar May 06 '23 07:05 Ishotihadus

I suspect this is a problem in the implementation of __setItem__.

I am clueless about C++ so I don't understand why, but in this code I had to take a pointer to the item list map before modifying it.

Edit: take this with a grain of salt, I have not reproduced the problem yet.

jacobvosmaer avatar May 06 '23 08:05 jacobvosmaer

@Ishotihadus I am not able to reproduce the segfault. I tried the following, on 189fa6b.

bundle exec rake
ruby -Ilib -rtaglib test.rb

With test.rb being:

f = TagLib::MP4::File.new('test/data/mp4.m4a')

100.times do
  f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
end

puts f.tag.item_map.to_h

This prints a Ruby hash, as expected, without segfaulting.

jacobvosmaer avatar May 06 '23 09:05 jacobvosmaer

Could you try this code? This always fails in my environment even without irb.

# frozen_string_literal: true

require 'net/http'
require 'json'

100.times do
  f = TagLib::MP4::File.new('test.m4a')
  f.tag['©nam'] = TagLib::MP4::Item.from_string_list(['name'])
  f.tag['©ART'] = TagLib::MP4::Item.from_string_list(['artist'])

  request = Net::HTTP::Post.new(URI.parse('https://example.com'))
  request.content_type = 'application/x-www-form-urlencoded;charset=UTF-8'
  request.set_form_data('name' => f.tag['©nam'].to_string_list[0], 'artist' => f.tag['©ART'].to_string_list[0])
  Net::HTTP.start('example.com', 443, use_ssl: true) { |http| http.request(request) }

  f.tag['©lyr'] = TagLib::MP4::Item.from_string_list(['a'])
end

I have a feeling that something in the memory handling around strings is causing this problem, but I am not sure.

  • taglib-ruby: 1.1.3 / 189fa6b
  • taglib: 1.13 (via Homebrew)

Ishotihadus avatar May 06 '23 16:05 Ishotihadus

@Ishotihadus that reproducer still does nothing on my end. I'm also using a mac and taglib 1.13.

  1. What ruby version are you using?
  2. Does your reproducer work if you use the test file from taglib-ruby?

jacobvosmaer avatar May 07 '23 08:05 jacobvosmaer

  1. I use Ruby 3.2.2 from rbenv without customization.
  2. Yes. I can even reproduce the problem with the test file. I have MacBook Pro and Mac Studio, but the problem occurs on both hardwares.

My environment has

  • macOS 13.3.1 (a)
  • Ruby 3.2.2 from rbenv (2023-03-30 revision e51014f9c0) [arm64-darwin22]

My Gemflie.lock is: Gemfile.lock. I also attach logs of bundle exec rake: rake.log; but I think there is no valuable information in this log.

Thanks for your supporting.

Ishotihadus avatar May 09 '23 04:05 Ishotihadus

I found this problem appears on Ruby >= 3.2.0 and does not appear on Ruby <= 3.1.4! I use Ruby 3.1.4 for taglib-ruby for now!

Ishotihadus avatar May 09 '23 04:05 Ishotihadus

Thanks. Using ruby 3.2.2 I also get the segfault.

I can't get rid of the HTTP request in the reproducer yet; writing the tag values to /dev/null breaks the reproducer.

jacobvosmaer avatar May 09 '23 09:05 jacobvosmaer

The segfault also happens if I replace f.tag['©lyr'] = ... with f.tag.empty?. Looks like f.tag is a Ruby object pointing to a garbage memory address?

jacobvosmaer avatar May 09 '23 10:05 jacobvosmaer

I've narrowed down the reproducer a bit.

require 'net/http'

def do_stuff
  Net::HTTP.get('localhost', '/', 8080)
end

$stdout.sync=true

1000.times do |i|
  printf("%d ", i)

  f = TagLib::MP4::File.new('test/data/mp4.m4a')
  f.tag['©ART'] = TagLib::MP4::Item.from_string_list(['artist'])

  do_stuff

  f.tag.empty?
  f.close
end

puts

I still don't understand why I can't get rid of net/http here.

The number of iterations before a segfault seems to be kind of stable. It varies if you make small changes to the code, such as adding another f.tag[xxx] =.

jacobvosmaer avatar May 19 '23 11:05 jacobvosmaer

Interesting. What might help narrowing it down is to see if any of the specific TagLib functionality triggers it. E.g. if you remove from_string_list and use a different tag, can you still reproduce? If not, that would suggest the problem is somewhere in our handling of string lists (just an example).

robinst avatar Jun 24 '23 08:06 robinst

Also, reading through the Ruby 3.2 release notes, it looks like YJIT is now enabled by default? Does the problem also occur if you disable it on 3.2 (not sure if that's possible?) or if you enable it on < 3.2?

robinst avatar Jun 24 '23 08:06 robinst

Good idea, but YJIT does not seem to be active when I reproduce the bug. I checked by adding puts "YJIT enabled: #{RubyVM::YJIT.enabled?}" which reports false.

Replacing from_string_list with e.g. from_int does not make the crash go away. Replacing the f.tag[xxx] = with f.tag.empty? still triggers the crash.

require 'net/http'

def do_stuff
  Net::HTTP.get('localhost', '/', 8080)
end

$stdout.sync=true

puts "YJIT enabled: #{RubyVM::YJIT.enabled?}"

1000.times do
  f = TagLib::MP4::File.new('test/data/mp4.m4a')
  f.tag.empty?

  do_stuff

  f.tag.empty? # <- second call to #empty? triggers segfault
  f.close
end

puts

jacobvosmaer avatar Jun 24 '23 10:06 jacobvosmaer

To be clear, it's not about #empty?, that is just a conveniently succise method call. It also crashes if you call #album or something else.

It seems as if the HTTP request eventually causes the tag to get deallocated somewhere (in C++?).

jacobvosmaer avatar Jun 24 '23 10:06 jacobvosmaer