mruby-regexp: quote the pattern as written in RegexpError messages - #7031
Merged
Conversation
`compile_error()` formatted `c->src`, the text the parser reads. In extended
mode `mrb_re_compile()` points `c->src` at the buffer `strip_extended()`
returns, so the message quoted a pattern with the free-spacing and the
comments already removed.
```ruby
Regexp.new("a # c\n[", Regexp::EXTENDED)
# CRuby: RegexpError (premature end of char-class: /a # c\n[/x)
# mruby: RegexpError (unterminated character class: /a[/)
Regexp.new("a b(", Regexp::EXTENDED)
# CRuby: RegexpError (end pattern with unmatched parenthesis: /a b(/x)
# mruby: RegexpError (unmatched '(': /ab(/)
```
Keep the caller's pointer and length in `orig` and `orig_end`, set before the
extended-mode block replaces them, and quote those instead. The parser still
reads the preprocessed text; only the message changes. Ordinary patterns are
unaffected, since `c->src` is then already the caller's buffer.
The new pointer is the caller's buffer and outlives the compile: the single
caller is `regexp_init()`, which stores the same String in `@source` before
passing `RSTRING_PTR()`, so the bytes stay rooted across the allocating
`mrb_format()`. `orig` never points into `c->stripped`, so the message no
longer depends on the free order in `compile_error()`.
|
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)
📝 WalkthroughWalkthroughThe regexp compiler now retains the original pattern separately from its preprocessed source. Compilation errors use the original pattern and explicit length. Tests cover malformed extended-mode patterns with whitespace and comments. ChangesRegexp error source preservation
Estimated code review effort: 2 (Simple) | ~10 minutes 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 was referenced Aug 9, 2026
This was referenced Aug 17, 2026
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.
compile_error()formats the pattern the parser is reading. In/xmode thatis not the pattern the user wrote:
mrb_re_compile()pointsc->srcat thebuffer
strip_extended()returns, so the message quotes text with thefree-spacing and the comments taken out.
The comment that explained the pattern is gone from the message, and so is the
position the reader would use to find the error. Anything the pass removes goes
with it:
This is a diagnostics bug, not a behavioural one. The same patterns are accepted
and rejected either way; only the text of the exception differs.
Change
re_compilergainsorigandorig_endnext tosrcandsrc_end.mrb_re_compile()sets them from its arguments before the extended-mode blockreplaces
patternandlen, andcompile_error()quotes them instead ofsrcandsrc_end. The parser keeps reading the preprocessed text; this onlychanges what gets quoted. Ordinary patterns see no difference, since
c->srcis then already the caller's buffer.
The new pointer outlives the compile. The single caller is
regexp_init(),which stores the same String in
@sourcebefore passingRSTRING_PTR(), sothe bytes stay rooted across the allocating
mrb_format(). It also neverpoints into
c->stripped, so the message no longer depends on the free orderin
compile_error(); the comment there is updated to say what is quoted andwhy rather than to state a lifetime constraint that no longer applies.
Out of scope
CRuby appends the flags,
/a # c\n[/x. mruby's format string carries no flagsat all, for
/xor for anything else, which is a separate difference. Themessage wording (
unterminated character classagainst CRuby'spremature end of char-class) is another one; this gem's messages differ fromOnigmo's throughout.
Tests
Two
assert_raise_with_messagecases inassert("Regexp extended mode (x flag)")pin the whole message for a comment-bearing pattern and a whitespace-bearing
one. No existing assertion depended on the old text: the
RegexpErrorcases inthis file are all
assert_raisewithout a message.rake testpasses (1940 OK, 0 KO).Summary by CodeRabbit
Bug Fixes
Tests