php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #67705
Patch magicdata-56.patch revision 2014-07-29 08:32 UTC by remi@php.net
Patch magicdata-54.patch revision 2014-07-29 08:32 UTC by remi@php.net
Patch cve-2014-3538-php54.patch revision 2014-07-29 07:25 UTC by remi@php.net
Patch cve-2014-3538.patch revision 2014-07-29 06:44 UTC by remi@php.net

Patch cve-2014-3538.patch for Filesystem function related Bug #67705

Patch version 2014-07-29 06:44 UTC

Return to Bug #67705 | Download this patch
Patch Revisions:

Developer: remi@php.net

diff -up ./data_file.c.cve ./data_file.c
--- ./data_file.c.cve	2014-07-29 07:48:50.873006117 +0200
+++ ./data_file.c	2014-07-29 07:40:19.243602276 +0200
@@ -121057,7 +121057,7 @@ const unsigned char php_magic_database[2
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x40, 0x00, 0x3D, 0x1B, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x5E, 0x5C, 0x73, 0x7B, 0x30, 0x2C, 0x31, 0x30, 0x30, 0x7D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x5C, 
 0x73, 0x7B, 0x30, 0x2C, 0x31, 0x30, 0x30, 0x7D, 0x5B, 0x7B, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
diff -up ./libmagic/softmagic.c.cve ./libmagic/softmagic.c
--- ./libmagic/softmagic.c.cve	2014-07-29 07:49:11.599099224 +0200
+++ ./libmagic/softmagic.c	2014-07-29 08:28:27.170260472 +0200
@@ -67,7 +67,7 @@ private int32_t mprint(struct magic_set
 private int32_t moffset(struct magic_set *, struct magic *);
 private void mdebug(uint32_t, const char *, size_t);
 private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
-    const unsigned char *, uint32_t, size_t, size_t);
+    const unsigned char *, uint32_t, size_t, struct magic *);
 private int mconvert(struct magic_set *, struct magic *, int);
 private int print_sep(struct magic_set *, int);
 private int handle_annotation(struct magic_set *, struct magic *);
@@ -1038,7 +1038,7 @@ mdebug(uint32_t offset, const char *str,
 
 private int
 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
-    const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
+    const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
 {
 	/*
 	 * Note: FILE_SEARCH and FILE_REGEX do not actually copy
@@ -1058,15 +1058,24 @@ mcopy(struct magic_set *ms, union VALUET
 			const char *last;	/* end of search region */
 			const char *buf;	/* start of search region */
 			const char *end;
-			size_t lines;
+			size_t lines, linecnt, bytecnt;
 
+			linecnt = m->str_range;
+			bytecnt = linecnt * 80;
+
+			if (bytecnt == 0) {
+				bytecnt = 8192;
+			}
+			if (bytecnt > nbytes) {
+				bytecnt = nbytes;
+			}
 			if (s == NULL) {
 				ms->search.s_len = 0;
 				ms->search.s = NULL;
 				return 0;
 			}
 			buf = RCAST(const char *, s) + offset;
-			end = last = RCAST(const char *, s) + nbytes;
+			end = last = RCAST(const char *, s) + bytecnt;
 			/* mget() guarantees buf <= last */
 			for (lines = linecnt, b = buf; lines && b < end &&
 			     ((b = CAST(const char *,
@@ -1079,7 +1088,7 @@ mcopy(struct magic_set *ms, union VALUET
 					b++;
 			}
 			if (lines)
-				last = RCAST(const char *, s) + nbytes;
+				last = RCAST(const char *, s) + bytecnt;
 
 			ms->search.s = buf;
 			ms->search.s_len = last - buf;
@@ -1150,7 +1159,6 @@ mget(struct magic_set *ms, const unsigne
     int *need_separator, int *returnval)
 {
 	uint32_t soffset, offset = ms->offset;
-	uint32_t count = m->str_range;
 	int rv, oneed_separator, in_type;
 	char *sbuf, *rbuf;
 	union VALUETYPE *p = &ms->ms_value;
@@ -1162,13 +1170,12 @@ mget(struct magic_set *ms, const unsigne
 	}
 
 	if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o),
-	    (uint32_t)nbytes, count) == -1)
+	    (uint32_t)nbytes, m) == -1)
 		return -1;
 
 	if ((ms->flags & MAGIC_DEBUG) != 0) {
 		fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, "
-		    "nbytes=%zu, count=%u)\n", m->type, m->flag, offset, o,
-		    nbytes, count);
+		    "nbytes=%zu)\n", m->type, m->flag, offset, o, nbytes);
 		mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
 	}
 
@@ -1661,7 +1668,7 @@ mget(struct magic_set *ms, const unsigne
 			if ((ms->flags & MAGIC_DEBUG) != 0)
 				fprintf(stderr, "indirect +offs=%u\n", offset);
 		}
-		if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
+		if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1)
 			return -1;
 		ms->offset = offset;
 
@@ -2093,7 +2100,7 @@ magiccheck(struct magic_set *ms, struct
 			zval *retval;
 			zval *subpats;
 			char *haystack;
-			
+
 			MAKE_STD_ZVAL(retval);
 			ALLOC_INIT_ZVAL(subpats);
 			
diff -up ./tests/cve-2014-3538.phpt.cve ./tests/cve-2014-3538.phpt
--- ./tests/cve-2014-3538.phpt.cve	2014-07-29 08:24:03.654996032 +0200
+++ ./tests/cve-2014-3538.phpt	2014-07-29 08:25:58.839548904 +0200
@@ -0,0 +1,35 @@
+--TEST--
+Bug #66731: file: extensive backtraking
+--SKIPIF--
+<?php
+if (!class_exists('finfo'))
+	die('skip no fileinfo extension');
+--FILE--
+<?php
+$fd = __DIR__.'/cve-2014-3538.data';
+
+file_put_contents($fd,
+  'try:' .
+  str_repeat("\n", 1000000));
+
+$fi = finfo_open(FILEINFO_NONE);
+$t = microtime(true);
+var_dump(finfo_file($fi, $fd));
+$t = microtime(true) - $t;
+finfo_close($fi);
+if ($t < 1) {
+	echo "Ok\n";
+} else {
+	printf("Failed, time=%.2f\n", $t);
+}
+
+?>
+Done
+--CLEAN--
+<?php
+@unlink(__DIR__.'/cve-2014-3538.data');
+?>
+--EXPECTF--
+string(%d) "%s"
+Ok
+Done
\ Pas de fin de ligne à la fin du fichier
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 19:01:29 2024 UTC