Skip to content

Several read-only methods fail if StringIO is frozen #120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
headius opened this issue Feb 20, 2025 · 6 comments
Open

Several read-only methods fail if StringIO is frozen #120

headius opened this issue Feb 20, 2025 · 6 comments

Comments

@headius
Copy link
Contributor

headius commented Feb 20, 2025

Problem

While fixing a small regression from my recent StringIO fixes I discovered that a large number of read-only methods will fail if the StringIO is frozen. A few examples:

$ ruby -rstringio -e 's = StringIO.new; p s.lineno; s.freeze; p s.lineno' 
0
-e:1:in 'StringIO#lineno': can't modify frozen StringIO: #<StringIO:0x0000000103711ea8> (FrozenError)
	from -e:1:in '<main>'
$ ruby -rstringio -e 's = StringIO.new; p s.closed?; s.freeze; p s.closed?'
false
-e:1:in 'StringIO#closed?': can't modify frozen StringIO: #<StringIO:0x00000001008c1e68> (FrozenError)
	from -e:1:in '<main>'
$ ruby -rstringio -e 's = StringIO.new; p s.eof?; s.freeze; p s.eof?'
true
-e:1:in 'StringIO#eof?': can't modify frozen StringIO: #<StringIO:0x000000011c171e80> (FrozenError)
	from -e:1:in '<main>'
$ ruby -rstringio -e 's = StringIO.new; p s.pos; s.freeze; p s.pos'
0
-e:1:in 'StringIO#pos': can't modify frozen StringIO: #<StringIO:0x0000000105551df0> (FrozenError)
	from -e:1:in '<main>'

Cause

This is because the StringIO macro calls get_strio which calls rb_io_taint_check which calls rb_check_frozen. The StringIO macro is used in almost every method to access the rb_stringio_t data structure.

A list of methods I believe should be operable when the StringIO is frozen (in stringio.c definition order):

  • string (returns underlying String but does not mutate anything)
  • lineno
  • pos
  • closed?/closed_read?/closed_write?
  • eof/eof?
  • sync
  • pid (a dummy method but it writes nothing)
  • fileno (dummy)
  • pread (by definition does not modify state)
  • isatty/tty?
  • size/length
  • external_encoding
  • internal_encoding

In addition, initialize_copy probably should not require the original StringIO be writable:

$ cx 3.4 ruby -rstringio -e 's = StringIO.new("foo"); s.freeze; p s.dup'                                                                                           
-e:1:in 'StringIO#initialize_copy': can't modify frozen StringIO: #<StringIO:0x0000000102eb1df8> (FrozenError)
	from -e:1:in 'Kernel#initialize_dup'
	from -e:1:in 'Kernel#dup'
	from -e:1:in '<main>'

The data from the original StringIO is unmodified by initialize_copy, other than the reference-counting ptr->count (which should not be subject to frozen checks).

Origin

I believe most of these cases are caused by this change from 2011 that added frozen checks to StringIO (the class and the macro).
ruby/ruby@d8d9bac

Fix

Assuming we agree these read-only methods should work with a frozen, I'll modify them in the JRuby extension to do the equivalent of check_strio which only confirms the ptr has been initialized. Perhaps a StringIOReadOnly macro would make sense for CRuby.

@kou
Copy link
Member

kou commented Feb 20, 2025

Good catch!

But it seems that IO has the same behavior:

$  ruby -e 'File.open("README.md") {|f| f.freeze; f.lineno}'
-e:1:in 'IO#lineno': can't modify frozen File: #<File:README.md> (FrozenError)
	from -e:1:in 'block in <main>'
	from -e:1:in 'IO.open'
	from -e:1:in '<main>'

How about discussing this in https://bugs.ruby-lang.org/ not here? StringIO behavior should be aligned with IO behavior.

@headius
Copy link
Contributor Author

headius commented Feb 20, 2025

@kou I will open an issue on ruby-lang! Thanks!

@headius
Copy link
Contributor Author

headius commented Feb 20, 2025

@headius
Copy link
Contributor Author

headius commented Feb 20, 2025

@kou Given that this will take more discussion, so we can align IO and StringIO, could we get #119/#121 released? I would really appreciate it! 👍

@kou
Copy link
Member

kou commented Feb 21, 2025

OK. I'll release a new version with #121.

@kou
Copy link
Member

kou commented Feb 21, 2025

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants