Subject: Reduce recursion level from 20 to 10 and make a symbolic constant for it. (...) ID: CVE-2014-8117 Upstream-Author: Christos Zoulas Date: Sun Nov 23 13:54:27 2014 +0000 Origin: FILE5_20-29-g6f737dd Last-Update: 2015-01-05 - reduce recursion level from 20 to 10 and make a symbolic constant for it. - pull out the guts of saving and restoring the output buffer into functions and take care not to overwrite the error message if an error happened. diff --git a/src/file.h b/src/file.h index de262b2..6f61643 100644 --- a/src/file.h +++ b/src/file.h @@ -444,6 +444,14 @@ protected int file_os2_apptype(struct magic_set *, const char *, const void *, #endif /* __EMX__ */ +typedef struct { + char *buf; + uint32_t offset; +} file_pushbuf_t; + +protected file_pushbuf_t *file_push_buffer(struct magic_set *); +protected char *file_pop_buffer(struct magic_set *, file_pushbuf_t *); + #ifndef COMPILE_ONLY extern const char *file_names[]; extern const size_t file_nnames; diff --git a/src/funcs.c b/src/funcs.c index 0d645eb..04bab02 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -459,3 +459,43 @@ file_replace(struct magic_set *ms, const char *pat, const char *rep) return nm; } } + +protected file_pushbuf_t * +file_push_buffer(struct magic_set *ms) +{ + file_pushbuf_t *pb; + + if (ms->event_flags & EVENT_HAD_ERR) + return NULL; + + if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL) + return NULL; + + pb->buf = ms->o.buf; + pb->offset = ms->offset; + + ms->o.buf = NULL; + ms->offset = 0; + + return pb; +} + +protected char * +file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) +{ + char *rbuf; + + if (ms->event_flags & EVENT_HAD_ERR) { + free(pb->buf); + free(pb); + return NULL; + } + + rbuf = ms->o.buf; + + ms->o.buf = pb->buf; + ms->offset = pb->offset; + + free(pb); + return rbuf; +} diff --git a/src/softmagic.c b/src/softmagic.c index 72eae4b..0ace99f 100644 --- a/src/softmagic.c +++ b/src/softmagic.c @@ -61,6 +61,9 @@ private void cvt_32(union VALUETYPE *, const struct magic *); private void cvt_64(union VALUETYPE *, const struct magic *); #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) + +#define MAX_RECURSION_LEVEL 10 + /* * softmagic - lookup one file in parsed, in-memory copy of database * Passed the name and FILE * of one file to be typed. @@ -1044,11 +1047,12 @@ mget(struct magic_set *ms, const unsigned char *s, int recursion_level) { uint32_t offset = ms->offset; + file_pushbuf_t *pb; int rv; - char *sbuf, *rbuf; + char *rbuf; union VALUETYPE *p = &ms->ms_value; - if (recursion_level >= 20) { + if (recursion_level >= MAX_RECURSION_LEVEL) { file_error(ms, 0, "recursion nesting exceeded"); return -1; } @@ -1611,15 +1615,21 @@ mget(struct magic_set *ms, const unsigned char *s, return 0; if (nbytes < offset) return 0; - sbuf = ms->o.buf; - ms->o.buf = NULL; + + if ((pb = file_push_buffer(ms)) == NULL) + return -1; + rv = file_softmagic(ms, s + offset, nbytes - offset, recursion_level, BINTEST, text); + if ((ms->flags & MAGIC_DEBUG) != 0) fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); + + rbuf = file_pop_buffer(ms, pb); + if (rbuf == NULL) + return -1; + if (rv == 1) { - rbuf = ms->o.buf; - ms->o.buf = sbuf; if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && file_printf(ms, m->desc, offset) == -1) { free(rbuf); @@ -1629,9 +1639,8 @@ mget(struct magic_set *ms, const unsigned char *s, free(rbuf); return -1; } - free(rbuf); - } else - ms->o.buf = sbuf; + } + free(rbuf); return rv; case FILE_DEFAULT: /* nothing to check */