| Ticket UUID: | 75c9d9cece5612408603f4e56773f55ada24b2d7 | ||
| Title: | regexp sometimes allows an invalid backref to be matched | ||
| Type: | Bug | Created on: | 2021-08-23 16:04:19 |
| Submitter: | tgl | Assigned to: | jan.nijtmans |
| Subsystem: | 43. Regexp | Severity: | Minor |
| Priority: | 5 Medium | Last modified: | 2026-10-11 16:50:48 |
| Status: | Closed | Closed by: | jan.nijtmans |
| Resolution: | Fixed | Closed on: | 2026-10-11 16:50:48 |
| Version: | 8.6.18, 9.0.5, 9.1.0 | ||
| Description: | ||||
$ tclsh
% regexp {^(.)\1|\1.} {abcdef}
1
% regexp {^((.)\2|..)\2} {abadef}
1
Of course, neither of these should match, because the (.) capture is within a failed alternative branch,
so the last backref to it should be deemed unable to match.
Analysis and fix for it in Postgres is here:
https://www.postgresql.org/message-id/151435.1629733387%40sss.pgh.pa.us
I doubt you can use the code change exactly as-is, because I don't think you ever adopted our changes
to create an explicit "iteration" subre type. But the principle, and particularly the more careful
specification of cdissect's recursion rules, should still work for you.
| ||||
| User Comments: | ||||
serhiy.storchaka added on 2026-10-10 19:29:32:
Still the same in 8.6, 9.0 and 9.1. When the right side of a concatenation failed, ccondissect() and crevcondissect() left the captures of the left side set, so the next alternative's backref saw them. Proposed fix in branch regexp-backref-failed-alt: your PostgreSQL change, which clears the left side's captures when the right side fails and defines the cdissect() rules for clearing match data. Tests reg-14.30 and 14.31 (your examples). jan.nijtmans added on 2026-10-11 16:50:48:
Fixed in [9383b0c913592380|trunk], core-9-0-branch and core-8-6-branch Many thanks! | ||||
