git: f77b5b295da3 - main - Allow -DNO_STRICT_REGEX to restore historic regex behavior

From: Simon J. Gerraty <sjg_at_FreeBSD.org>
Date: Fri, 10 May 2024 01:30:59 UTC
The branch main has been updated by sjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=f77b5b295da3146c3b601767cbc4e85e6713192c

commit f77b5b295da3146c3b601767cbc4e85e6713192c
Author:     Simon J. Gerraty <sjg@FreeBSD.org>
AuthorDate: 2024-05-10 01:29:43 +0000
Commit:     Simon J. Gerraty <sjg@FreeBSD.org>
CommitDate: 2024-05-10 01:29:43 +0000

    Allow -DNO_STRICT_REGEX to restore historic regex behavior
    
    Allow restoring the behavior of '{' as described in regex(3).
    Ie. only treat it as start of bounds if followed by a digit.
    
    If NO_STRICT_REGEX is not defined, the behavior introduced by
    commit a4a801688c909ef39cbcbc3488bc4fdbabd69d66 is retained,
    otherwise the previous behavior is restored.
    
    Differential Revision:  https://reviews.freebsd.org/D45134
---
 lib/libc/regex/regcomp.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/lib/libc/regex/regcomp.c b/lib/libc/regex/regcomp.c
index 7481d3ecf240..f34dc322d0bb 100644
--- a/lib/libc/regex/regcomp.c
+++ b/lib/libc/regex/regcomp.c
@@ -453,7 +453,9 @@ p_ere_exp(struct parse *p, struct branchc *bc)
 	case '*':
 	case '+':
 	case '?':
+#ifndef NO_STRICT_REGEX
 	case '{':
+#endif
 		SETERROR(REG_BADRPT);
 		break;
 	case '.':
@@ -536,6 +538,11 @@ p_ere_exp(struct parse *p, struct branchc *bc)
 			break;
 		}
 		break;
+#ifdef NO_STRICT_REGEX
+	case '{':               /* okay as ordinary except if digit follows */
+	    (void)REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT);
+	    /* FALLTHROUGH */
+#endif
 	default:
 		if (p->error != 0)
 			return (false);
@@ -549,11 +556,19 @@ p_ere_exp(struct parse *p, struct branchc *bc)
 		return (false);
 	c = PEEK();
 	/* we call { a repetition if followed by a digit */
-	if (!( c == '*' || c == '+' || c == '?' || c == '{'))
+	if (!( c == '*' || c == '+' || c == '?' ||
+#ifdef NO_STRICT_REGEX
+	       (c == '{' && MORE2() && isdigit((uch)PEEK2()))
+#else
+	       c == '{'
+#endif
+	       ))
 		return (false);		/* no repetition, we're done */
+#ifndef NO_STRICT_REGEX
 	else if (c == '{')
 		(void)REQUIRE(MORE2() && \
 		    (isdigit((uch)PEEK2()) || PEEK2() == ','), REG_BADRPT);
+#endif
 	NEXT();
 
 	(void)REQUIRE(!wascaret, REG_BADRPT);
@@ -892,6 +907,9 @@ p_simp_re(struct parse *p, struct branchc *bc)
 			(void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
 			break;
 		case BACKSL|')':	/* should not get here -- must be user */
+#ifdef NO_STRICT_REGEX
+		case BACKSL|'}':
+#endif
 			SETERROR(REG_EPAREN);
 			break;
 		case BACKSL|'1':