Description: fix a heap overflow in regex library on 32 bit systems
Author: Guido Vranken
Origin: http://gitweb.dragonflybsd.org/dragonfly.git/blobdiff/4d133046c59a851141519d03553a70e903b3eefc..2841837793bd095a82f477e9c370cfe6cfb3862c:/lib/libc/regex/regcomp.c
Adapted: Ralf Treinen <treinen@debian.org>
Debian Bug: #778410

Index: yap/library/regex/regcomp.c
===================================================================
--- yap.orig/library/regex/regcomp.c	2013-11-23 15:34:01.000000000 +0100
+++ yap/library/regex/regcomp.c	2015-02-15 19:41:31.313641936 +0100
@@ -264,6 +264,7 @@
 	register struct parse *p = &pa;
 	register int i;
 	register size_t len;
+	size_t maxlen;
 #ifdef REDEBUG
 #	define	GOODFLAGS(f)	(f)
 #else
@@ -286,7 +287,23 @@
 							(NC-1)*sizeof(cat_t));
 	if (g == NULL)
 		return(REG_ESPACE);
+/*
+  Limit the pattern space to avoid a 32-bit overflow on buffer
+  extension.  Also avoid any signed overflow in case of conversion
+  so make the real limit based on a 31-bit overflow.
+
+  Likely not applicable on 64-bit systems but handle the case
+  generically (who are we to stop people from using ~715MB+
+  patterns?).
+*/
+	maxlen = ((size_t)-1 >> 1) / sizeof(sop) * 2 / 3;
+	if (len >= maxlen) {
+	  free((char *)g);
+	  return(REG_ESPACE);
+	}
 	p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */
+	assert(p->ssize >= len);
+	
 	p->strip = (sop *)malloc(p->ssize * sizeof(sop));
 	p->slen = 0;
 	if (p->strip == NULL) {
