Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Feb 2015 19:14:42 +0000 (UTC)
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r278911 - stable/9/lib/libc/regex
Message-ID:  <201502171914.t1HJEg3P083010@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: delphij
Date: Tue Feb 17 19:14:41 2015
New Revision: 278911
URL: https://svnweb.freebsd.org/changeset/base/278911

Log:
  MFC r278739:
  
  Disallow pattern spaces which would cause intermediate calculations to
  overflow size_t.
  
  Obtained from:	DragonFly (2841837793bd095a82f477e9c370cfe6cfb3862c dillon)
  Security:	CERT VU#695940

Modified:
  stable/9/lib/libc/regex/regcomp.c
Directory Properties:
  stable/9/lib/libc/   (props changed)

Modified: stable/9/lib/libc/regex/regcomp.c
==============================================================================
--- stable/9/lib/libc/regex/regcomp.c	Tue Feb 17 19:14:16 2015	(r278910)
+++ stable/9/lib/libc/regex/regcomp.c	Tue Feb 17 19:14:41 2015	(r278911)
@@ -192,6 +192,7 @@ regcomp(regex_t * __restrict preg,
 	struct parse *p = &pa;
 	int i;
 	size_t len;
+	size_t maxlen;
 #ifdef REDEBUG
 #	define	GOODFLAGS(f)	(f)
 #else
@@ -213,7 +214,23 @@ regcomp(regex_t * __restrict preg,
 	g = (struct re_guts *)malloc(sizeof(struct re_guts));
 	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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502171914.t1HJEg3P083010>