From 7f5f46013b8a37bab6b378903aace5da9ce8dc5e Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Sun, 4 Nov 2018 13:11:28 +0100 Subject: [PATCH] Rework places in libmagic regarding previous CVE-2014-3538 fixes CVE-2014-3538 was fixed upstream, but the old patch was still kept in the PHP port. This patch causes performance regressions when PCRE JIT is not enabled. This is fixed by applying the relevant original code from the newer libmagic, which makes the old patch obsolete as the CVE-2014-3538 tests still pass. --- ext/fileinfo/libmagic/apprentice.c | 7 ++++--- ext/fileinfo/libmagic/softmagic.c | 33 ++++++++++++------------------ 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/ext/fileinfo/libmagic/apprentice.c b/ext/fileinfo/libmagic/apprentice.c index 2035544c5c..94e4302d61 100644 --- a/ext/fileinfo/libmagic/apprentice.c +++ b/ext/fileinfo/libmagic/apprentice.c @@ -2567,18 +2567,19 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action) return -1; } if (m->type == FILE_REGEX) { - /* XXX do we need this? */ - /*zval pattern; + zval pattern; int options = 0; pcre_cache_entry *pce; convert_libmagic_pattern(&pattern, m->value.s, strlen(m->value.s), options); if ((pce = pcre_get_compiled_regex_cache(Z_STR(pattern))) == NULL) { + zval_dtor(&pattern); return -1; } + zval_dtor(&pattern); - return 0;*/ + return 0; } return 0; default: diff --git a/ext/fileinfo/libmagic/softmagic.c b/ext/fileinfo/libmagic/softmagic.c index b25f48f1e4..e9d45ff2b9 100644 --- a/ext/fileinfo/libmagic/softmagic.c +++ b/ext/fileinfo/libmagic/softmagic.c @@ -1268,28 +1268,21 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, return 0; } - /* bytecnt checks are to be kept for PHP, see cve-2014-3538. - PCRE might get stuck if the input buffer is too big. */ - linecnt = m->str_range; - bytecnt = linecnt * 80; - - if (bytecnt == 0) { - bytecnt = 1 << 14; + if (m->str_flags & REGEX_LINE_COUNT) { + linecnt = m->str_range; + bytecnt = linecnt * 80; + } else { + linecnt = 0; + bytecnt = m->str_range; } - if (bytecnt > nbytes) { - bytecnt = nbytes; - } - if (offset > bytecnt) { - offset = bytecnt; - } - if (s == NULL) { - ms->search.s_len = 0; - ms->search.s = NULL; - return 0; - } + if (bytecnt == 0 || bytecnt > nbytes - offset) + bytecnt = nbytes - offset; + if (bytecnt > ms->regex_max) + bytecnt = ms->regex_max; + buf = RCAST(const char *, s) + offset; - end = last = RCAST(const char *, s) + bytecnt; + end = last = RCAST(const char *, s) + bytecnt + offset; /* mget() guarantees buf <= last */ for (lines = linecnt, b = buf; lines && b < end && ((b = CAST(const char *, @@ -1302,7 +1295,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, b++; } if (lines) - last = RCAST(const char *, s) + bytecnt; + last = end; ms->search.s = buf; ms->search.s_len = last - buf; -- 2.40.0