Segmentation fault on Lion creating NSData from RubyCocoa with any bytes > 127

917 Views Asked by At

The following RubyCocoa is fine on Max OS X 10.6, but segfaults on 10.7

require 'osx/cocoa'
include OSX
bytes = [128].pack('i1')
NSData.alloc.initWithBytes_length(bytes, bytes.length)

In all cases it works when the top bit is not set. In fact NSData.alloc seems to fail when passed a buffer where any of the bytes have the top bit set.

The version of Ruby is 1.8.7 on both OS's, so I'm at a loss to diagnose why NSData is interpreting the buffer differently. Can anyone shed any light?

4

There are 4 best solutions below

0
On BEST ANSWER

This is fixed in RubyCocoa 1.0.2

1
On

You should probably go for MacRuby as it will replace RubyCocoa. It's possible that RubyCocoa does not (and will never) work properly on Lion.

I don't have any MacRuby experience with Lion yet, but chances are good that it will work.

1
On

MacRuby is still unfinished - it just doesn't work with some of the ruby code I work with. I've run into the same NSData problem, and I was able to create a CFData instance which appears ok with the following code

gem 'RubyInline'
require 'inline'

class CFDataWrapper
  begin 
    inline do |builder|
      builder.include "<CoreFoundation/CoreFoundation.h>"
      builder.c_raw_singleton "

      static VALUE fromString(int argc, VALUE *args){
        CFDataRef d = CFDataCreate(NULL, RSTRING_PTR(args[0]), RSTRING_LEN(args[0]));    

        VALUE result;
        char type = '@';
        ocdata_to_rbobj(Qnil,&type, (const void *)&d, &result, false) ;
        return result;
      }
    "
    end
  end
end
bytes = [128].pack('i1')
data = CFDataWrapper.fromString(bytes)
puts data.inspect

The output from inspect is different from under 10.6 but I can pass it back into methods that expect NSData instances and they appear to work, call NSData methods on it etc. Beyond this toy script it works a script i use to populate core data documents, where one of the entities has a binary data attribute

1
On

I will guess that the problem is actually pack corrupting memory because it is not handling the signed overflow in a good way. Some things to try that may lead you to the answer:

  • try pack('C1')
  • Dump out bytes, compare to irb's output.
  • call some other function which allocates memory right after the pack (not using bytes at all).