Project

General

Profile

Actions

Bug #11827

closed

StringIO with set_encoding broken with enabled frozen string literal

Added by deepj (deepj #) over 8 years ago. Updated over 8 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.3.0preview2 (2015-12-11 trunk 53028) [x86_64-darwin15]
[ruby-core:72189]

Description

I'm not sure if this the following problem is an expected behavior. But I guess, it is a bug when I run the code below. It throws `set_encoding': can't modify frozen String (RuntimeError).

# frozen_string_literal: true

io = StringIO.new('')
io.set_encoding(Encoding::BINARY)

I wouldn't expect this kind of behavior.

Updated by shugo (Shugo Maeda) over 8 years ago

  • Status changed from Open to Feedback

deepj # wrote:

I'm not sure if this the following problem is an expected behavior. But I guess, it is a bug when I run the code below. It throws `set_encoding': can't modify frozen String (RuntimeError).

# frozen_string_literal: true

io = StringIO.new('')
io.set_encoding(Encoding::BINARY)

I wouldn't expect this kind of behavior.

What behavior do you expect?

StringIO is a wrapper to provide IO-like interface for String, so the argument of StringIO.new should not be copied.

s = "foo"
io = StringIO.new(s)
io.putc(?b)
p s #=> "boo"

If you specify writable mode explicitly, you can get an exception earlier:

# frozen_string_literal: true

io = StringIO.new("", "w") #=> Errno::EACCESS

Updated by deepj (deepj #) over 8 years ago

Shugo Maeda wrote:

What behavior do you expect?

Not throw the exception in this case. I guess this is a better example https://github.com/rack/rack/blob/master/lib/rack/mock.rb#L139

Here is set an encoding for IO classes included StringIO. When the frozen string literal is enabled it causes a problem obviously. And there is no way (at least I haven't figured out it) how to change an encoding for a StringIO with frozen string. For me it wouldn't be any difference with I have a StringIO with a frozen string, or a File. It's just a interface with same expected behaviour of IO-like classes. In this case a change of encoding. So a string would be mutable in StringIO when it was immutable previously. I might be wrong here.

Updated by naruse (Yui NARUSE) over 8 years ago

deepj # wrote:

Shugo Maeda wrote:

What behavior do you expect?

Not throw the exception in this case. I guess this is a better example https://github.com/rack/rack/blob/master/lib/rack/mock.rb#L139

Here is set an encoding for IO classes included StringIO. When the frozen string literal is enabled it causes a problem obviously. And there is no way (at least I haven't figured out it) how to change an encoding for a StringIO with frozen string. For me it wouldn't be any difference with I have a StringIO with a frozen string, or a File. It's just a interface with same expected behavior of IO-like classes. In this case a change of encoding. So a string would be mutable in StringIO when it was immutable previously. I might be wrong here.

In this case ''.force_encoding(Encoding::ASCII_8BIT) should be String.new.force_encoding(Encoding::ASCII_8BIT)
(or String.new(encoding: Encoding::ASCII_8BIT) for Ruby 2.3)

Away from the case and thinking ideal behavior, StringIO should be a view of given source string and set_encoding shouldn't change source encoding.
But I'm not sure that it is worth breaking the compatibility.

Actions #4

Updated by shugo (Shugo Maeda) over 8 years ago

Yui NARUSE wrote:

Away from the case and thinking ideal behavior, StringIO should be a view of given source string and set_encoding shouldn't change source encoding.
But I'm not sure that it is worth breaking the compatibility.

FYI, nobu figured out that open-uri depends on the current behavior:

      enc = Encoding::ASCII_8BIT unless enc
      if self.respond_to? :force_encoding
        self.force_encoding(enc)
      elsif self.respond_to? :string
        self.string.force_encoding(enc)
      else # Tempfile
        self.set_encoding enc
      end
    end
Actions #5

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Status changed from Feedback to Closed

Applied in changeset r53188.


stringio.c: separate encoding from buffer

  • ext/stringio/stringio.c (strio_set_encoding): add StringIO's own
    encoding and separate it from the buffer string to override the
    encoding of string when reading. [ruby-core:72189] [Bug #11827]
    note that setting the encoding of its buffer string may cause
    unpredictable behavior.
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0