Skip to content

Fix use-after-free: bind Regex lifetime to custom Syntax via PhantomData#222

Merged
iwillspeak merged 4 commits into
mainfrom
copilot/fix-lifetime-mismatch-regex-options
Apr 27, 2026
Merged

Fix use-after-free: bind Regex lifetime to custom Syntax via PhantomData#222
iwillspeak merged 4 commits into
mainfrom
copilot/fix-lifetime-mismatch-regex-options

Conversation

Copilot AI commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

The Oniguruma C engine permanently stores the syntax pointer inside re_pattern_buffer (via onig_reg_init), but the safe Rust API did not express this dependency — allowing a custom Syntax to be dropped while the Regex was still live, yielding a dangling pointer.

Approach

Add a 'syntax lifetime parameter to Regex backed by PhantomData<&'syntax Syntax>, surfacing the C-level memory dependency to the borrow checker at zero runtime cost.

Changes

  • Regex<'syntax> — new lifetime parameter + _syntax: PhantomData<&'syntax Syntax> field; Send/Sync/Drop impls updated accordingly.
  • Constructors:
    • new / with_encoding → explicitly return Regex<'static> (use Syntax::default() which is 'static; no new restriction on callers)
    • with_options<'s>(..., syntax: &'s Syntax) -> Result<Regex<'s>, Error> — returned Regex cannot outlive syntax
    • with_options_and_encoding<'s, T>(..., syntax: &'s Syntax) -> Result<Regex<'s>, Error> — same
  • Iterator types'syntax added as an independent lifetime parameter (separate from the regex reference lifetime 'r):
    • FindMatches<'r, 'syntax, 't>, FindCaptures<'r, 'syntax, 't>, RegexSplits<'r, 'syntax, 't>, RegexSplitsN<'r, 'syntax, 't>
  • pattern.rsRegexSearcher<'r, 'syntax, 'a>; impl<'r, 'syntax> Pattern for &'r Regex<'syntax>

Example

// Before: compiled fine, but custom_syntax could be freed while regex was live
let regex = {
    let custom_syntax = *Syntax::default();
    Regex::with_options("hello", RegexOptions::REGEX_OPTION_NONE, &custom_syntax).unwrap()
    // custom_syntax dropped here — dangling pointer in the C engine
};

// After: compiler rejects this — `custom_syntax does not live long enough`

Callers using Regex::new or Regex::with_options(..., Syntax::default()) are unaffected — the returned type is Regex<'static>.

@iwillspeak iwillspeak requested review from Keats and Copilot and removed request for Keats April 26, 2026 09:31
@iwillspeak iwillspeak marked this pull request as ready for review April 26, 2026 09:31
@iwillspeak

Copy link
Copy Markdown
Collaborator

What do we think @Keats ? Adds a lifetime requirement to Regex so we'd have to bump but it does seem like the right thing to do here.

Copilot AI changed the title [WIP] Fix potential lifetime mismatch in Regex::with_options Fix use-after-free: bind Regex lifetime to custom Syntax via PhantomData Apr 26, 2026
Copilot AI requested a review from iwillspeak April 26, 2026 09:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the onig crate’s Regex type to carry an explicit lifetime tying it to the Syntax used at compile time, preventing a compiled regex from outliving a custom (non-static) Syntax.

Changes:

  • Introduce Regex<'syntax> with a PhantomData<&'syntax Syntax> marker to enforce correct syntax lifetimes.
  • Update constructors (new, with_encoding, with_options, with_options_and_encoding) to return Regex values with appropriate lifetimes ('static for default syntax, otherwise tied to the provided &Syntax).
  • Propagate the new Regex<'syntax> type through related impl blocks and add a test demonstrating the lifetime enforcement.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
onig/src/lib.rs Adds Regex<'syntax> + PhantomData, updates constructors’ return types, updates Drop/Send/Sync, and adds a lifetime-enforcement test.
onig/src/find.rs Adjusts Regex impl block to be generic over 'syntax (propagating the new Regex<'syntax> type).
onig/src/pattern.rs Updates Pattern integration to work with the lifetime-parameterized Regex.
onig/src/names.rs Updates inherent impl block to Regex<'syntax>.
onig/src/replace.rs Updates inherent impl block to Regex<'syntax>.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread onig/src/lib.rs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@iwillspeak iwillspeak mentioned this pull request Apr 27, 2026
@Keats

Keats commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

I think that's fine? 99% of the usage will be 'static anyway

@iwillspeak iwillspeak merged commit 0fcf518 into main Apr 27, 2026
23 checks passed
@iwillspeak iwillspeak deleted the copilot/fix-lifetime-mismatch-regex-options branch April 27, 2026 10:43
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

Successfully merging this pull request may close these issues.

Potential lifetime mismatch in Regex::with_options when using custom Syntax

4 participants