aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-07-18 21:22:43 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2013-07-18 21:22:43 -0400
commitf8463fba2434d083bb699d1cc8a7d7159d614a7b (patch)
tree43b45110435914edf61a44a27127f2ef69f97e0a /src
parentdd8ea2eb5e996f3f3dfd928e20aa2462c4bd9c63 (diff)
downloadpostgresql-f8463fba2434d083bb699d1cc8a7d7159d614a7b.tar.gz
postgresql-f8463fba2434d083bb699d1cc8a7d7159d614a7b.zip
Fix regex match failures for backrefs combined with non-greedy quantifiers.
An ancient logic error in cfindloop() could cause the regex engine to fail to find matches that begin later than the start of the string. This function is only used when the regex pattern contains a back reference, and so far as we can tell the error is only reachable if the pattern is non-greedy (i.e. its first quantifier uses the ? modifier). Furthermore, the actual match must begin after some potential match that satisfies the DFA but then fails the back-reference's match test. Reported and fixed by Jeevan Chalke, with cosmetic adjustments by me.
Diffstat (limited to 'src')
-rw-r--r--src/backend/regex/regexec.c20
-rw-r--r--src/test/regress/expected/regex.out15
-rw-r--r--src/test/regress/sql/regex.sql5
3 files changed, 31 insertions, 9 deletions
diff --git a/src/backend/regex/regexec.c b/src/backend/regex/regexec.c
index 3748a9c1714..78ebdee39e4 100644
--- a/src/backend/regex/regexec.c
+++ b/src/backend/regex/regexec.c
@@ -487,19 +487,21 @@ cfindloop(struct vars * v,
*coldp = cold;
return er;
}
- if ((shorter) ? end == estop : end == begin)
- {
- /* no point in trying again */
- *coldp = cold;
- return REG_NOMATCH;
- }
- /* go around and try again */
+ /* try next shorter/longer match with same begin point */
if (shorter)
+ {
+ if (end == estop)
+ break; /* NOTE BREAK OUT */
estart = end + 1;
+ }
else
+ {
+ if (end == begin)
+ break; /* NOTE BREAK OUT */
estop = end - 1;
- }
- }
+ }
+ } /* end loop over endpoint positions */
+ } /* end loop over beginning positions */
} while (close < v->stop);
*coldp = cold;
diff --git a/src/test/regress/expected/regex.out b/src/test/regress/expected/regex.out
index 757f2a4028a..df39ef937dd 100644
--- a/src/test/regress/expected/regex.out
+++ b/src/test/regress/expected/regex.out
@@ -173,3 +173,18 @@ select 'a' ~ '((((((a+|)+|)+|)+|)+|)+|)';
t
(1 row)
+-- Test backref in combination with non-greedy quantifier
+-- https://core.tcl.tk/tcl/tktview/6585b21ca8fa6f3678d442b97241fdd43dba2ec0
+select 'Programmer' ~ '(\w).*?\1' as t;
+ t
+---
+ t
+(1 row)
+
+select regexp_matches('Programmer', '(\w)(.*?\1)', 'g');
+ regexp_matches
+----------------
+ {r,ogr}
+ {m,m}
+(2 rows)
+
diff --git a/src/test/regress/sql/regex.sql b/src/test/regress/sql/regex.sql
index 1426562119a..e5f690263b9 100644
--- a/src/test/regress/sql/regex.sql
+++ b/src/test/regress/sql/regex.sql
@@ -41,3 +41,8 @@ select 'a' ~ '($|^)*';
-- Test for infinite loop in fixempties() (Tcl bugs 3604074, 3606683)
select 'a' ~ '((((((a)*)*)*)*)*)*';
select 'a' ~ '((((((a+|)+|)+|)+|)+|)+|)';
+
+-- Test backref in combination with non-greedy quantifier
+-- https://core.tcl.tk/tcl/tktview/6585b21ca8fa6f3678d442b97241fdd43dba2ec0
+select 'Programmer' ~ '(\w).*?\1' as t;
+select regexp_matches('Programmer', '(\w)(.*?\1)', 'g');