Uploaded image for project: 'Ruby Driver'
  1. Ruby Driver
  2. RUBY-2043

BSON::Binary fails to serialize if data is frozen

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • bson-4.7.0
    • Affects Version/s: None
    • Component/s: BSON
    • Labels:
      None
    • Minor Change

      If a BSON::Binary is created with a frozen string as an argument, the to_bson call on the binary fails:

      irb(main):002:0> BSON::Binary.new('test'.freeze).to_bson
      Traceback (most recent call last):
              6: from /home/me/.rbenv/versions/2.6/bin/irb:23:in `<main>'
              5: from /home/me/.rbenv/versions/2.6/bin/irb:23:in `load'
              4: from /home/me/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
              3: from (irb):2
              2: from /home/me/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bson-4.6.0/lib/bson/binary.rb:139:in `to_bson'
              1: from /home/me/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bson-4.6.0/lib/bson/binary.rb:139:in `force_encoding'
      FrozenError (can't modify frozen String)
      

      This is because during serialization, the code calls force_encoding which mutates the receiver (in this case the data string originally provided to the constructor).

      To fix this, if the string provided to the constructor is not in binary encoding, the constructor will dup it and set encoding to binary. Subsequently serialization does not need to perform any data conversions.

      One caveat with this is the encoding of the Binary data is now always going to be binary:

      irb(main):002:0> foo = 'test'
      => "test"
      irb(main):003:0> foo.encoding
      => #<Encoding:US-ASCII>
      irb(main):004:0> bin = BSON::Binary.new(foo)
      => <BSON::Binary:0x47211276836200 type=generic data=0x74657374...>
      irb(main):005:0> bin.data  
      => "test"
      irb(main):006:0> bin.data.encoding
      => #<Encoding:ASCII-8BIT>
      

      This can cause issues for code that expected the data in the Binary to be in the original encoding. However, this use case is not quite correct because, for example, persisting the data to the server and retrieving it back will make the data available in the binary encoding. User code should assume that the data stored in a BSON::Binary is, in fact, a binary string - always.

            Assignee:
            oleg.pudeyev@mongodb.com Oleg Pudeyev (Inactive)
            Reporter:
            oleg.pudeyev@mongodb.com Oleg Pudeyev (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: