]> git.eshelyaron.com Git - emacs.git/commit
Fix ‘[[:cc:]]*literal’ regex failing to match ‘literal’ (bug#24020)
authorMichal Nazarewicz <mina86@mina86.com>
Mon, 18 Jul 2016 13:59:26 +0000 (15:59 +0200)
committerMichal Nazarewicz <mina86@mina86.com>
Mon, 25 Jul 2016 21:52:27 +0000 (23:52 +0200)
commit6dc6b0079ed3632ed9082bc79d8cb6fc96d33f43
treeffad067337d44c6b559f474fb7421fa7fcf892c6
parentb176d169347925d57ca63ab63b85d92e49a53c81
Fix ‘[[:cc:]]*literal’ regex failing to match ‘literal’ (bug#24020)

The regex engine tries to optimise Kleene star by avoiding backtracking
when it can detect that star’s operand cannot match what follows it in
the pattern.

For example, when ‘[[:alpha:]]*1’ tries to match a ‘foo’, the engine
will test the longest match for ‘[[:alpha:]]*’, namely ’foo’ which is
the entire string.  Literal digit one still present in the pattern will
however not match the remaining empty string.

Normally, backtracking would be performed trying a shorter match for the
character class (namely ‘fo’ leaving ‘o’ in the string), but since the
engine knows whatever would be put back into the string cannot possibly
match literal digit one so no backtracking will be attempted.

In the regexes of the form ‘[[:CC:]]*X’, the optimisation can be applied
if the character class CC does not match character X.  In the above
example, this holds because digit one is not in alpha character class.

This test is performed by mutually_exclusive_p function but it did not
check class bits of a charset opcode.  This resulted in an assumption
that character classes do not match multibyte characters.  For example,
it would incorrectly conclude that [[:alpha:]] doesn’t match ‘ż’.

This, in turn, led to the aforementioned Kleene star optimisation being
incorrectly applied in patterns such as ‘[[:graph:]]*☠’ (which should
match ‘☠’ but doesn’t as can be tested by executing
    (string-match-p "[[:graph:]]*☠" "☠")
which should return 0 but instead yields nil.

This issue affects any class witch matches multibyte characters, i.e.
if ‘[[:cc:]]’ matches a multibyte character X then ‘[[:cc:]]*X’ will
fail to match ‘X’.

* src/regex.c (executing_charset): A new function for executing the
charset and charset_not opcodes.  It performs check on the character
taking into consideration existing bitmap, range table and class bits.
It also advances the pointer in the regex bytecode past the parsed
opcode.
(CHARSET_LOOKUP_RANGE_TABLE_RAW, CHARSET_LOOKUP_RANGE_TABLE): Removed.
Code now included in executing_charset.
(mutually_exclusive_p, re_match_2_internal): Changed to take advantage
of executing_charset function.

* test/src/regex-tests.el: New file with tests for the character class
matching.
src/regex.c
test/src/regex-tests.el [new file with mode: 0644]