CVE-2014-3538 (Other, published 2014-07-03T14:55Z)
Description: value: file before 5.19 does not properly restrict the amount of data read during a regex search, which allows remote attackers to cause a denial of service (CPU consumption) via a crafted file that triggers backtracking during processing of an awk rule.  NOTE: this vulnerability exists because of an incomplete fix for CVE-2013-7345.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-399 \u2014 Resource Management Errors
Weaknesses in this category are related to improper management of system resources.
Repository: https://github.com/file/file
Files changed:
ChangeLog
doc/magic.man
magic/Magdir/android
magic/Magdir/fortran
magic/Magdir/graphviz
magic/Magdir/marc21
magic/Magdir/scientific
magic/Magdir/troff
src/apprentice.c
src/file.h
src/softmagic.c
Commit message: * Enforce limit of 8K on regex searches that have no limits
* Allow the l modifier for regex to mean line count. Default
  to byte count. If line count is specified, assume a max
  of 80 characters per line to limit the byte count.
* Don't allow conversions to be used for dates, allowing
  the mask field to be used as an offset.
* Bump the version of the magic format so that regex changes
  are visible.


Vulnerable code:
.\" $File: magic.man,v 1.82 2014/05/30 16:51:23 christos Exp $
.Dv /[c][s] .
# $File: android,v 1.2 2013/11/05 14:00:25 christos Exp $
>>19    regex/1		\^([^n\n]|n[^o]|no[^n]|non[^e]|none.+).*	\b, Encrypted (%s)
#>>>&1		regex/1 .*	\b, Password salt: %s
#>>>>&1		regex/1 .*	\b, Master salt: %s
#>>>>>&1	regex/1 .*	\b, PBKDF2 rounds: %s
#>>>>>>&1	regex/1 .*	\b, IV: %s
#>>>>>>>&1	regex/1 .*	\b, Key: %s
# $File: fortran,v 1.6 2009/09/19 16:28:09 christos Exp $
0	regex/100	\^[Cc][\ \t]	FORTRAN program
# $File$
#0	regex/100	[\r\n\t\ ]*graph[\r\n\t\ ]+.*\\{	graphviz graph text
#0	regex/100	[\r\n\t\ ]*digraph[\r\n\t\ ]+.*\\{	graphviz digraph text
>0	regex/1	(^[0-9]{5})[acdnp][^bhlnqsu-z]	MARC21 Bibliographic
>0	regex/1	(^[0-9]{5})[acdnosx][z]	MARC21 Authority
>0	regex/1	(^[0-9]{5})[cdn][uvxy]	MARC21 Holdings
0	regex/1	(^[0-9]{5})[acdn][w]	MARC21 Classification
>0	regex/1	(^[0-9]{5})[cdn][q]	MARC21 Community
>0	regex/1	(^.{21})([^0]{2})	(non-conforming)
# $File: scientific,v 1.7 2010/09/20 19:19:17 rrt Exp $
>&0	regex/1	\^.{40}
>>&0	regex/1	[0-9]{2}-[A-Z]{3}-[0-9]{2}\ {3}
>>>&0	regex/1s	[A-Z0-9]{4}.{14}$
>>>>&0	regex/1	[A-Z0-9]{4}	Protein Data Bank data, ID Code %s
>>>>0	regex/1	[0-9]{2}-[A-Z]{3}-[0-9]{2}	\b, %s
# $File$
0	regex/20	\^\\.[A-Za-z0-9][A-Za-z0-9][\ \t]	troff or preprocessor input text
0	regex/20	\^\\.[A-Za-z0-9][A-Za-z0-9]$	troff or preprocessor input text
FILE_RCSID("@(#)$File: apprentice.c,v 1.209 2014/05/13 16:42:17 christos Exp $")
	if (m->type != FILE_PSTRING && (m->str_flags & PSTRING_LEN) != 0) {
					if (m->type != FILE_PSTRING)
 * @(#)$File: file.h,v 1.150 2014/05/05 20:53:10 christos Exp $
#define VERSIONNO	11
FILE_RCSID("@(#)$File: softmagic.c,v 1.188 2014/05/14 23:15:42 christos Exp $")
    const unsigned char *, uint32_t, size_t, size_t);
		    file_fmttime(p->l, FILE_T_LOCAL, tbuf)) == -1)
		    file_fmttime(p->l, 0, tbuf)) == -1)
		    file_fmttime(p->q, FILE_T_LOCAL, tbuf)) == -1)
		    file_fmttime(p->q, 0, tbuf)) == -1)
		    file_fmttime(p->q, FILE_T_WINDOWS, tbuf)) == -1)
	switch (cvt_flip(m->type, flip)) {
		cvt_32(p, m);
		cvt_64(p, m);
		cvt_32(p, m);
		cvt_64(p, m);
		cvt_32(p, m);
    const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
			size_t lines;
			end = last = RCAST(const char *, s) + nbytes;
				last = RCAST(const char *, s) + nbytes;
	uint32_t count = m->str_range;
	    (uint32_t)nbytes, count) == -1)
		    "nbytes=%zu, count=%u)\n", m->type, m->flag, offset, o,
		    nbytes, count);
		if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
			v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
#ifndef REG_STARTEND
			char c;
#endif
			/* Limit by offset if requested */
			if (m->str_range > 0)
				slen = MIN(slen, m->str_range);

Fixed code:
2014-06-02  14:50  Christos Zoulas <christos@zoulas.com>

	* Enforce limit of 8K on regex searches that have no limits
	* Allow the l modifier for regex to mean line count. Default
	  to byte count. If line count is specified, assume a max
	  of 80 characters per line to limit the byte count.
	* Don't allow conversions to be used for dates, allowing
	  the mask field to be used as an offset.

.\" $File: magic.man,v 1.83 2014/06/03 17:36:13 christos Exp $
.Dv /[c][s][l] .
The
.Dq l
modifier, changes the limit of length to mean number of lines instead of a
byte count.
Lines are delimited by the platforms native line delimiter.
When a line count is specified, an implicit byte count also computed assuming
each line is 80 characters long.
If neither a byte or line count is specified, the search is limited automatically
to 8KiB.
Numeric operations are not performed on date types, instead the numeric
value is interpreted as an offset.
.Pp
# $File: android,v 1.3 2013/11/08 01:24:22 christos Exp $
>>19    regex/1l	\^([^n\n]|n[^o]|no[^n]|non[^e]|none.+).*	\b, Encrypted (%s)
#>>>&1		regex/1l .*	\b, Password salt: %s
#>>>>&1		regex/1l .*	\b, Master salt: %s
#>>>>>&1	regex/1l .*	\b, PBKDF2 rounds: %s
#>>>>>>&1	regex/1l .*	\b, IV: %s
#>>>>>>>&1	regex/1l .*	\b, Key: %s
# $File: fortran,v 1.7 2012/06/21 01:55:02 christos Exp $
0	regex/100l	\^[Cc][\ \t]	FORTRAN program
# $File: graphviz,v 1.7 2009/09/19 16:28:09 christos Exp $
#0	regex/100l	[\r\n\t\ ]*graph[\r\n\t\ ]+.*\\{	graphviz graph text
#0	regex/100l	[\r\n\t\ ]*digraph[\r\n\t\ ]+.*\\{	graphviz digraph text
>0	regex/1l	(^[0-9]{5})[acdnp][^bhlnqsu-z]	MARC21 Bibliographic
>0	regex/1l	(^[0-9]{5})[acdnosx][z]	MARC21 Authority
>0	regex/1l	(^[0-9]{5})[cdn][uvxy]	MARC21 Holdings
0	regex/1l	(^[0-9]{5})[acdn][w]	MARC21 Classification
>0	regex/1l	(^[0-9]{5})[cdn][q]	MARC21 Community
>0	regex/1l	(^.{21})([^0]{2})	(non-conforming)
# $File: scientific,v 1.8 2014/01/06 17:46:23 rrt Exp $
>&0	regex/1l	\^.{40}
>>&0	regex/1l	[0-9]{2}-[A-Z]{3}-[0-9]{2}\ {3}
>>>&0	regex/1ls	[A-Z0-9]{4}.{14}$
>>>>&0	regex/1l	[A-Z0-9]{4}	Protein Data Bank data, ID Code %s
>>>>0	regex/1l	[0-9]{2}-[A-Z]{3}-[0-9]{2}	\b, %s
# $File: troff,v 1.10 2009/09/19 16:28:12 christos Exp $
0	regex/20l	\^\\.[A-Za-z0-9][A-Za-z0-9][\ \t]	troff or preprocessor input text
0	regex/20l	\^\\.[A-Za-z0-9][A-Za-z0-9]$	troff or preprocessor input text
FILE_RCSID("@(#)$File: apprentice.c,v 1.210 2014/05/14 23:15:42 christos Exp $")
	if ((m->type != FILE_REGEX || (m->str_flags & REGEX_LINE_COUNT) == 0) &&
	    (m->type != FILE_PSTRING && (m->str_flags & PSTRING_LEN) != 0)) {
					switch (m->type) {
					case FILE_PSTRING:
					case FILE_REGEX:
						break;
					default:
					}
 * @(#)$File: file.h,v 1.151 2014/05/14 23:15:42 christos Exp $
#define VERSIONNO	12
#define REGEX_LINE_COUNT			BIT(11)
FILE_RCSID("@(#)$File: softmagic.c,v 1.189 2014/05/30 16:47:44 christos Exp $")
    const unsigned char *, uint32_t, size_t, struct magic *);
		    file_fmttime(p->l + m->num_mask, FILE_T_LOCAL, tbuf)) == -1)
		    file_fmttime(p->l + m->num_mask, 0, tbuf)) == -1)
		    file_fmttime(p->q + m->num_mask, FILE_T_LOCAL, tbuf)) == -1)
		    file_fmttime(p->q + m->num_mask, 0, tbuf)) == -1)
		    file_fmttime(p->q + m->num_mask, FILE_T_WINDOWS, tbuf)) == -1)
	uint8_t type;
	switch (type = cvt_flip(m->type, flip)) {
		if (type == FILE_BELONG)
			cvt_32(p, m);
		if (type == FILE_BEQUAD)
			cvt_64(p, m);
		if (type == FILE_LELONG)
			cvt_32(p, m);
		if (type == FILE_LEQUAD)
			cvt_64(p, m);
		if (type == FILE_MELONG)
			cvt_32(p, m);
    const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
			size_t lines, linecnt, bytecnt;

			if (m->str_flags & REGEX_LINE_COUNT) {
				linecnt = m->str_range;
				bytecnt = linecnt * 80;
			} else {
				linecnt = 0;
				bytecnt = m->str_range;
			}

			if (bytecnt == 0)
				bytecnt = 8192;
			if (bytecnt > nbytes)
				bytecnt = nbytes;

			end = last = RCAST(const char *, s) + bytecnt;
				last = RCAST(const char *, s) + bytecnt;
	    (uint32_t)nbytes, m) == -1)
		    "nbytes=%zu)\n", m->type, m->flag, offset, o, nbytes);
		if (mcopy(ms, p, m->type, 0, s, offset, nbytes, m) == -1)
			v = file_strncmp(m->value.s, ms->search.s + idx, slen,
			    m->str_flags);
			char c;