Skip to content

Make REG_LITERAL match the empty pattern - #146

Open
kevinushey wants to merge 2 commits into
laurikari:masterfrom
kevinushey:fix-literal-empty
Open

Make REG_LITERAL match the empty pattern#146
kevinushey wants to merge 2 commits into
laurikari:masterfrom
kevinushey:fix-literal-empty

Conversation

@kevinushey

Copy link
Copy Markdown

These pull requests were generated with Claude Code, but were reviewed by me (@kevinushey) before posting. I'll respond personally to any feedback; please let me know if this is okay.


This makes REG_LITERAL match the empty pattern.

Problem. With REG_LITERAL, compiling an empty pattern succeeds, but the resulting regex never matches anything — including the empty string:

tre_regcomp(&re, "", REG_EXTENDED | REG_LITERAL);
tre_regexec(&re, "abc", 1, m, 0);   /* returns REG_NOMATCH */

Expected: an empty pattern matches the empty string at offset 0 in any subject, as it does without REG_LITERAL and in other regex engines.

Cause. The PARSE_ATOM empty-expression branch is explicitly skipped in literal mode (!(ctx->cflags & REG_LITERAL) && ...), so an empty pattern falls through without ever producing an atom.

Fix. In literal mode at end of pattern, emit an EMPTY literal node, mirroring the non-literal branch. The guard uses ctx->re >= ctx->re_end so it also covers tre_regncomp(&re, "", 0, ...).

Testing (Windows x64, mingw-w64 gcc 14):

compile "" LITERAL                           PASS
"" matches in "abc" at (0,0)                 PASS   (unpatched: FAIL)
"" matches in "" at (0,0)                    PASS   (unpatched: FAIL)
regncomp len=0 LITERAL matches               PASS   (unpatched: FAIL)
literal "a.c" still matches only "a.c"       PASS
non-literal "" still matches (baseline)      PASS

Provenance. A variant of this fix has been carried in GNU R's vendored copy of TRE since 2009, where REG_LITERAL backs R's fixed = TRUE matching.

With REG_LITERAL, compiling an empty pattern succeeds but the
resulting regex never matches anything:

    tre_regcomp(&re, "", REG_EXTENDED | REG_LITERAL);
    tre_regexec(&re, "abc", 1, m, 0);   /* REG_NOMATCH; expected match */

The PARSE_ATOM empty-expression branch is skipped in literal mode, so
an empty pattern falls through without producing an atom. Emit an
EMPTY literal node in that case, matching the behavior of the
non-literal parser (and of an empty pattern in other regex engines).

A variant of this fix has been carried in GNU R's vendored copy of TRE
(where it backs fixed = TRUE matching) since 2009.
The suite had no REG_LITERAL coverage; these cases cover the
empty-pattern fix in this branch and literal handling of
metacharacters.
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.

1 participant