After a lot of time I finally got the test suite to pass and was happy, naïvely thinking that "if it passes the tests it must be correct". Unfortunately I also integrated a nice case of catastrophic backtracking into the regex that timgraham fortunately caught. This could have resulted in DoS-attacks against web forms that contain validated URL fields. (This is especially nice when doing it against non-asynchronous Python servers.)
https://github.com/django/django/pull/2873
This beast was finally merged half a year later:
^(?:[a-z0-9\\.\\-])://(?:\\S+(?::\\S)?@)?(?:(?:25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}|\\[[0-9a-f:\\.]+\\]|([a-z\u00a1-\uffff0-9](?:[a-z\u00a1-\uffff0-9-][a-z\u00a1-\uffff0-9])?(?:\\.[a-z\u00a1-\uffff0-9]+(?:[a-z\u00a1-\uffff0-9-][a-z\u00a1-\uffff0-9]+))\\.[a-z\u00a1-\uffff]{2,}\\.?|localhost))(?::\\d{2,5})?(?:[/?#][^\\s]*)?$
(.*)\1
is not context-free.Also it's not clear if regexes with backreferences can parse XML, which is context-free.