Skip to content

String#scrub! on invalid UTF-8 String causes internal exception #2398

@postmodern

Description

@postmodern

Discovered this bug while adding Encoding support to the 1.0.0 branch of hexdump.rb. The bug is triggered when String#scrub!('.') is called on a UTF-8 String containing an invalid byte sequence. Note that the file does have the magic # frozen_string_literal: true, so the '.' String is frozen.

Steps to Reproduce

binary = String.new("A\x80\x81B", encoding: Encoding::BINARY)
binary.force_encoding(Encoding::UTF_8)
binary.scrub!('.'.freeze) # Note: the freeze is to emulate frozen_string_literal: true

Expected Result

"A..B"

Actual Result

org.truffleruby.core.string.ImmutableRubyString cannot be cast to org.truffleruby.core.string.RubyString (java.lang.ClassCastException)
	from org.truffleruby.core.string.StringNodes$ScrubNode.scrubAsciiCompat(StringNodes.java:1925)
	from org.truffleruby.core.string.StringNodesFactory$ScrubNodeFactory$ScrubNodeGen.executeAndSpecialize(StringNodesFactory.java:5462)
	from org.truffleruby.core.string.StringNodesFactory$ScrubNodeFactory$ScrubNodeGen.execute(StringNodesFactory.java:5441)
	from org.truffleruby.language.control.SequenceNode.execute(SequenceNode.java:36)
	from org.truffleruby.language.control.IfElseNode.execute(IfElseNode.java:45)
	from org.truffleruby.language.control.SequenceNode.execute(SequenceNode.java:36)
	from org.truffleruby.language.arguments.CheckArityNode.execute(CheckArityNode.java:45)
	from org.truffleruby.language.methods.CatchForMethodNode.execute(CatchForMethodNode.java:42)
	from org.truffleruby.language.methods.ExceptionTranslatingNode.execute(ExceptionTranslatingNode.java:33)
	from org.truffleruby.language.RubyRootNode.execute(RubyRootNode.java:61)
	from org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.executeRootNode(OptimizedCallTarget.java:613)
<internal:core> core/string.rb:1023:in `scrub'
	from <internal:core> core/string.rb:1023:in `scrub!'
	from (irb):3:in `<top (required)>'
	from <internal:core> core/kernel.rb:325:in `eval'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb/workspace.rb:116:in `evaluate'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb/context.rb:450:in `evaluate'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb.rb:557:in `block (2 levels) in eval_input'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb.rb:741:in `signal_status'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb.rb:538:in `block in eval_input'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb/ruby-lex.rb:237:in `block (2 levels) in each_top_level_statement'
	from <internal:core> core/kernel.rb:437:in `loop'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb/ruby-lex.rb:219:in `block in each_top_level_statement'
	from <internal:core> core/throw_catch.rb:36:in `catch'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb/ruby-lex.rb:218:in `each_top_level_statement'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb.rb:537:in `eval_input'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb.rb:472:in `block in run'
	from <internal:core> core/throw_catch.rb:36:in `catch'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb.rb:471:in `run'
	from /opt/rubies/truffleruby-21.1.0/lib/mri/irb.rb:400:in `start'
	from /opt/rubies/truffleruby-21.1.0/lib/gems/gems/irb-1.3.3/exe/irb:11:in `<top (required)>'
	from <internal:core> core/kernel.rb:400:in `load'
	from <internal:core> core/kernel.rb:400:in `load'
	from /opt/rubies/truffleruby-21.1.0/bin/irb:42:in `<main>'

Additional Information

truffleruby 21.1.0, like ruby 2.7.2, GraalVM CE Native [x86_64-linux]
LANG=en_US.UTF-8

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions