From 8f297058512e6744b8d9f0bafe35689c702fce67 Mon Sep 17 00:00:00 2001 From: Shishir Jaiswal Date: Tue, 29 Nov 2016 11:19:30 +0530 Subject: [PATCH] Bug#24449090 - BUFFER OVERFLOW IN FUNCTION DUPL DESCRIPTION =========== Performing a pattern match of a Regex resulting into a very large string, leads to crash due to failed realloc(). ANALYSIS ======== dupl() calls enlarge(). It in turn calls realloc() for pointer p->strip. This eventually fails due to OOM. However we are still using the same pointer in memcpy() causing a SEGFAULT! FIX === 1) In dupl(), checking for error code (which would be set if realloc fails) immediately after call to enlarge(). Returning now with this error code. 2) Handling the same in the caller functions. --- regex/regcomp.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/regex/regcomp.c b/regex/regcomp.c index b1074a1d79c..e7feb9301e6 100644 --- a/regex/regcomp.c +++ b/regex/regcomp.c @@ -3,7 +3,7 @@ This file was modified by Oracle on 2015-05-18 for 32-bit compatibility. - Modifications copyright (c) 2015, Oracle and/or its affiliates. All rights + Modifications copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ #include @@ -551,6 +551,8 @@ int starordinary; /* is a leading * an ordinary character? */ assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); assert(OP(p->strip[p->pend[i]]) == ORPAREN); (void) dupl(p, p->pbegin[i]+1, p->pend[i]); + if (p->error != 0) + break; /* purecov: inspected */ EMIT(O_BACK, i); } else SETERROR(REG_ESUBREG); @@ -1031,6 +1033,8 @@ int to; /* to this number of times (maybe RE_INFINITY) */ AHEAD(THERE()); /* ...so fix it */ ASTERN(O_CH, THERETHERE()); copy = dupl(p, start+1, finish+1); + if (p->error != 0) + return; /* purecov: inspected */ assert(copy == finish+4); repeat(p, copy, 1, to-1); break; @@ -1040,10 +1044,14 @@ int to; /* to this number of times (maybe RE_INFINITY) */ break; case REP(N, N): /* as xx{m-1,n-1} */ copy = dupl(p, start, finish); + if (p->error != 0) + return; repeat(p, copy, from-1, to-1); break; case REP(N, INF): /* as xx{n-1,INF} */ copy = dupl(p, start, finish); + if (p->error != 0) + return; /* purecov: inspected */ repeat(p, copy, from-1, to); break; default: /* "can't happen" */ @@ -1366,6 +1374,9 @@ sopno finish; /* to this less one */ if (len == 0) return(ret); enlarge(p, p->ssize + len); /* this many unexpected additions */ + if (p->error != 0) + return(p->error); + assert(p->ssize >= p->slen + len); (void) memcpy((char *)(p->strip + p->slen), (char *)(p->strip + start), (size_t)len*sizeof(sop)); @@ -1482,6 +1493,14 @@ register sopno size; if (p->ssize >= size) return; + DBUG_EXECUTE_IF("bug24449090_simulate_oom", + { + p->strip= NULL; + p->ssize= 0; + SETERROR(REG_ESPACE); + return; + }); + sp = (sop *)realloc(p->strip, size*sizeof(sop)); if (sp == NULL) { SETERROR(REG_ESPACE);