shithub: kwa

Download patch

ref: 1a3cfdc5f7293bf426a14056002204169790b11b
parent: 83a948f226f910ddabb573499996f55502d19b23
author: qwx <qwx@sciops.net>
date: Wed Jan 7 13:07:47 EST 2026

fix use after free in regexp cache

--- a/lib.c
+++ b/lib.c
@@ -399,7 +399,8 @@
 			break;
 		}
 	}
-	return i;		
+	releasere(p);
+	return i;
 }
 
 void recbld(void)	/* create $0 from $1..$NF if necessary */
--- a/proto.h
+++ b/proto.h
@@ -11,6 +11,7 @@
 extern	void	unput(int);
 extern	void	unputstr(char *);
 
+extern	void	releasere(void *);
 extern	void	*compre(char *);
 extern	int	hexstr(char **);
 extern	void	quoted(char **, char **, char *);
--- a/re.c
+++ b/re.c
@@ -40,11 +40,24 @@
 {
 	char	*re;
 	int	use;
+	int inuse;
 	Reprog	*program;
 } pattern[NPATS];
 
 static int npats;		/* cache fill level */
 
+void
+releasere(void *p)
+{
+	int i;
+
+	for (i = 0; i < npats; i++)
+		if (pattern[i].program == p) {
+			pattern[i].inuse--;
+			break;
+		}
+}
+
 	/* Compile a pattern */
 void
 *compre(char *pat)
@@ -57,6 +70,7 @@
 		for (i = 0; i < npats; i++)
 			if (!strcmp(pat, pattern[i].re)) {
 				pattern[i].use++;
+				pattern[i].inuse++;
 				return((void *) pattern[i].program);
 			}
 	}
@@ -138,20 +152,25 @@
 		if (npats < NPATS)	/* Room in cache */
 			i = npats++;
 		else {			/* Throw out least used */
-			int use = pattern[0].use;
-			i = 0;
-			for (j = 1; j < NPATS; j++) {
-				if (pattern[j].use < use) {
+			int use = -1U;
+			i = -1;
+			for (j = 0; j < NPATS; j++) {
+				if (pattern[j].inuse == 0 && pattern[j].use < use) {
 					use = pattern[j].use;
 					i = j;
 				}
 			}
-			xfree(pattern[i].program);
-			xfree(pattern[i].re);
+			if (i >= 0) {
+				xfree(pattern[i].program);
+				xfree(pattern[i].re);
+			}
 		}
-		pattern[i].re = tostring(pat);
-		pattern[i].program = program;
-		pattern[i].use = 1;
+		if (i >= 0) {
+			pattern[i].re = tostring(pat);
+			pattern[i].program = program;
+			pattern[i].use = 1;
+			pattern[i].inuse = 1;
+		}
 	}
 	return((void *) program);
 }
--- a/run.c
+++ b/run.c
@@ -582,6 +582,7 @@
 		i = pmatch(p, s, s);
 	else
 		i = match(p, s, s);
+	releasere(p);
 	if (istemp(x))
 		tfree(x);
 	if (n == MATCHFCN) {
@@ -1301,8 +1302,7 @@
 		else
 			setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
   spdone:
-		p = nil;
-		USED(p);
+  		releasere(p);
 	} else if (sep == ' ') {
 		for (n = 0; ; ) {
 			while (*s == ' ' || *s == '\t' || *s == '\n')
@@ -1863,6 +1863,7 @@
 		setsval(x, buf);	/* BUG: should be able to avoid copy */
 		result = True;;
 	}
+	releasere(p);
 	if (istemp(x))
 		tfree(x);
 	if (istemp(y))
@@ -1960,6 +1961,7 @@
 			;
 		setsval(x, buf);	/* BUG: should be able to avoid copy + free */
 	}
+	releasere(p);
 	if (istemp(x))
 		tfree(x);
 	if (istemp(y))
--