diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c index c4aa14e..8368b39 100644 --- a/src/pcre2_compile.c +++ b/src/pcre2_compile.c @@ -3535,8 +3535,12 @@ while (ptr < ptrend) /* If x appears twice it sets the extended extended option. */ case CHAR_x: - *optset |= ((*optset & PCRE2_EXTENDED) != 0)? - PCRE2_EXTENDED_MORE : PCRE2_EXTENDED; + *optset |= PCRE2_EXTENDED; + if (ptr < ptrend && *ptr == CHAR_x) + { + *optset |= PCRE2_EXTENDED_MORE; + ptr++; + } break; default: @@ -3545,12 +3549,17 @@ while (ptr < ptrend) goto FAILED; } } + + /* If we are setting extended without extended-more, ensure that any + existing extended-more gets unset. Also, unsetting extended must also + unset extended-more. */ + + if ((set & (PCRE2_EXTENDED|PCRE2_EXTENDED_MORE)) == PCRE2_EXTENDED || + (unset & PCRE2_EXTENDED) != 0) + unset |= PCRE2_EXTENDED_MORE; + options = (options | set) & (~unset); - /* Unsetting extended should also get rid of extended-more. */ - - if ((options & PCRE2_EXTENDED) == 0) options &= ~PCRE2_EXTENDED_MORE; - /* If the options ended with ')' this is not the start of a nested group with option changes, so the options change at this level. In this case, if the previous level set up a nest block, discard the diff --git a/testdata/testinput1 b/testdata/testinput1 index 8c76e21..24de5b0 100644 --- a/testdata/testinput1 +++ b/testdata/testinput1 @@ -6146,4 +6146,16 @@ ef) x/x,mark # -------------------------------------------------------------------------- +/<(?x:[a b])>/xx + < > + +/<(?:[a b])>/xx + < > + +/<(?xxx:[a b])>/ + < > + +/<(?-x:[a b])>/xx + < > + # End of testinput1 diff --git a/testdata/testoutput1 b/testdata/testoutput1 index 85c1aad..ca955f2 100644 --- a/testdata/testoutput1 +++ b/testdata/testoutput1 @@ -9739,4 +9739,20 @@ No match # -------------------------------------------------------------------------- +/<(?x:[a b])>/xx + < > + 0: < > + +/<(?:[a b])>/xx + < > +No match + +/<(?xxx:[a b])>/ + < > +No match + +/<(?-x:[a b])>/xx + < > + 0: < > + # End of testinput1