The regex repetition count in lex(1) has no upper bound. Large
values parsed by myctoi() via sscanf("%d") are passed to mkrep()
in nfa.c where the expression lb - 1 overflows signed int:
base_mach = copysingl(mach, lb - 1);
The loop at nfa.c line 567 also iterates an unbounded number of
times with large bounds:
for (i = lb; i < ub; ++i)
POSIX defines _POSIX_RE_DUP_MAX (255) as the upper bound for
repetition counts. OpenBSD's regex library already enforces this.
The fix is in mkrep() rather than myctoi() because myctoi() is
also used to parse line numbers (scan.l:233) where the 255 limit
would be incorrect.
Found by AFL++ fuzzing with UBSan.
Index: usr.bin/lex/nfa.c
===================================================================
RCS file: /cvs/src/usr.bin/lex/nfa.c,v
retrieving revision 1.12
diff -u -p -r1.12 nfa.c
--- usr.bin/lex/nfa.c 9 Nov 2024 18:03:44 -0000 1.12
+++ usr.bin/lex/nfa.c
@@ -554,6 +554,10 @@ mkrep(int mach, int lb, int ub)
{
int base_mach, tail, copy, i;
+ if (lb > _POSIX_RE_DUP_MAX || (ub > _POSIX_RE_DUP_MAX &&
+ ub != INFINITE_REPEAT))
+ flexfatal(_("repetition value too large"));
+
base_mach = copysingl(mach, lb - 1);
if (ub == INFINITE_REPEAT) {