1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
Subject: file does not properly restrict the amount of data read during a regex search
ID: CVE-2014-3538
Author: Christos Zoulas <christos@zoulas.com>
Date: Tue Jun 3 19:01:34 2014 +0000
Origin:
commit 4a284c89d6ef11aca34da65da7d673050a5ea320
Debian-Author: Christoph Biedl <debian.axhn@manchmal.in-ulm.de>
Comment:
Taken from the fix in php5 (5.4.4-14+deb7u13), with minor corrections.
Last-Update: 2014-09-07
* 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.
--- a/src/softmagic.c
+++ b/src/softmagic.c
@@ -51,7 +51,7 @@
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 *);
private int print_sep(struct magic_set *, int);
private int handle_annotation(struct magic_set *, struct magic *);
@@ -918,7 +918,7 @@
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
@@ -938,15 +938,24 @@
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 *,
@@ -959,7 +968,7 @@
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;
@@ -1032,7 +1041,6 @@
int recursion_level)
{
uint32_t offset = ms->offset;
- uint32_t count = m->str_range;
union VALUETYPE *p = &ms->ms_value;
if (recursion_level >= 20) {
@@ -1040,7 +1048,8 @@
return -1;
}
- if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
+ if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset,
+ (uint32_t)nbytes, m) == -1)
return -1;
if ((ms->flags & MAGIC_DEBUG) != 0) {
@@ -1527,7 +1536,7 @@
if (m->flag & INDIROFFADD) {
offset += ms->c.li[cont_level-1].off;
}
- 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;
|