]> granicus.if.org Git - php/commitdiff
Rework places in libmagic regarding previous CVE-2014-3538 fixes
authorAnatol Belski <ab@php.net>
Sun, 4 Nov 2018 12:11:28 +0000 (13:11 +0100)
committerAnatol Belski <ab@php.net>
Sun, 4 Nov 2018 12:11:28 +0000 (13:11 +0100)
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
ext/fileinfo/libmagic/softmagic.c

index 2035544c5cd06aea24aa23aa0a6e61cf9b9f4805..94e4302d619e031a017b80b355f5fc403d579a8b 100644 (file)
@@ -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:
index b25f48f1e4a979c699747d9754547e1d4ffdddc7..e9d45ff2b94f17fc576759b39460e06a0d432181 100644 (file)
@@ -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;