mruby-regexp: String#split steps by a byte through a binary subject - #7085
Merged
Conversation
An empty match leaves `split` where it started, so the loop steps forward
before searching again. The step read the rest of the subject as UTF-8 and
cleared a whole character. A string marked by `String#b` has one position per
byte and `__byte_match` finds an empty match at every one of them, so the
fields came back joined.
```ruby
"\u{1F600}".b.split(//) # was ["\xF0\x9F\x98\x80"], CRuby: ["\xF0", "\x9F", "\x98", "\x80"]
"a\u{E9}b".b.split(//) # was ["a", "\xC3\xA9", "b"], CRuby: ["a", "\xC3", "\xA9", "b"]
```
The step asks `byteslice` for the rest of the subject and takes its first
element, and `byteslice` hands back a string that carries no `MRB_STR_BINARY`,
so that element is a whole character again however the subject was marked.
Read the flag off the subject with `Regexp.__binary_string?` and step by a
byte, which is what `gsub` already does at the same point and for the same
reason. A subject read as UTF-8 still steps by a character, and the limit
still counts fields.
`split("")` asks the same thing of the core implementation, which counted
bytes for such a string all along, so the two spellings agree again.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthrough
ChangesEncoding-aware split advancement
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An empty match leaves
splitwhere it started, so the loop steps forwardbefore searching again. The step read the rest of the subject as UTF-8 and
cleared a whole character. A string marked by
String#bhas one position perbyte and
__byte_matchfinds an empty match at every one of them, so thefields came back joined.
The same subject came apart two ways depending on which spelling of the same
request was used.
The change
splitreads the flag off the subject withRegexp.__binary_string?andsteps by a byte, which is what
gsuba few lines above already does at thesame point and for the same reason. Nothing else in the loop moves: a subject
read as UTF-8 still steps by a character, and the limit still counts fields.
Why the step cannot read it off the slice
The step asks
byteslicefor the rest of the subject and takes its firstelement.
byteslicebuilds that string withmrb_str_byte_subseq(), whichcopies
MRB_STR_SINGLE_BYTEand notMRB_STR_BINARY, so the slice arrivesunmarked and its first element is a whole character again however the subject
was marked. Reading the flag off the subject asks nothing of the slice.
Whether a slice of a binary string should itself be binary is a question about
src/string.cand is left alone here.Testing
rake testis green onfull-corewith gcc onx86_64-linux, with andwithout
MRB_REGEXP_UNICODE_CASE: 2215 and 2214 asserts, no failures. The newtest fails without the change:
Checked against CRuby 4.0.6, including the limit forms
split(//, 2)andsplit(//, -1), an empty subject, and an ASCII subject marked byString#b.Summary by CodeRabbit
Bug Fixes
String#splitbehavior with zero-length regular-expression matches.Tests