123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- Subject: PR/479: Protect against 0-divide and offset out of bounds reads
- Origin: FILE5_25-2-gde23336
- Upstream-Author: Christos Zoulas <christos@zoulas.com>
- Date: Wed Sep 16 18:25:23 2015 +0000
- --- a/src/softmagic.c
- +++ b/src/softmagic.c
- @@ -57,10 +57,10 @@
- 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 *);
- -private void cvt_8(union VALUETYPE *, const struct magic *);
- -private void cvt_16(union VALUETYPE *, const struct magic *);
- -private void cvt_32(union VALUETYPE *, const struct magic *);
- -private void cvt_64(union VALUETYPE *, const struct magic *);
- +private int cvt_8(union VALUETYPE *, const struct magic *);
- +private int cvt_16(union VALUETYPE *, const struct magic *);
- +private int cvt_32(union VALUETYPE *, const struct magic *);
- +private int cvt_64(union VALUETYPE *, const struct magic *);
-
- #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o)))
- #define BE64(p) (((uint64_t)(p)->hq[0]<<56)|((uint64_t)(p)->hq[1]<<48)| \
- @@ -858,37 +858,45 @@
- p->fld *= cast m->num_mask; \
- break; \
- case FILE_OPDIVIDE: \
- + if (cast m->num_mask == 0) \
- + return -1; \
- p->fld /= cast m->num_mask; \
- break; \
- case FILE_OPMODULO: \
- + if (cast m->num_mask == 0) \
- + return -1; \
- p->fld %= cast m->num_mask; \
- break; \
- } \
- if (m->mask_op & FILE_OPINVERSE) \
- p->fld = ~p->fld \
-
- -private void
- +private int
- cvt_8(union VALUETYPE *p, const struct magic *m)
- {
- DO_CVT(b, (uint8_t));
- + return 0;
- }
-
- -private void
- +private int
- cvt_16(union VALUETYPE *p, const struct magic *m)
- {
- DO_CVT(h, (uint16_t));
- + return 0;
- }
-
- -private void
- +private int
- cvt_32(union VALUETYPE *p, const struct magic *m)
- {
- DO_CVT(l, (uint32_t));
- + return 0;
- }
-
- -private void
- +private int
- cvt_64(union VALUETYPE *p, const struct magic *m)
- {
- DO_CVT(q, (uint64_t));
- + return 0;
- }
-
- #define DO_CVT2(fld, cast) \
- @@ -904,20 +912,24 @@
- p->fld *= cast m->num_mask; \
- break; \
- case FILE_OPDIVIDE: \
- + if (cast m->num_mask == 0) \
- + return -1; \
- p->fld /= cast m->num_mask; \
- break; \
- } \
-
- -private void
- +private int
- cvt_float(union VALUETYPE *p, const struct magic *m)
- {
- DO_CVT2(f, (float));
- + return 0;
- }
-
- -private void
- +private int
- cvt_double(union VALUETYPE *p, const struct magic *m)
- {
- DO_CVT2(d, (double));
- + return 0;
- }
-
- /*
- @@ -933,21 +945,25 @@
-
- switch (type = cvt_flip(m->type, flip)) {
- case FILE_BYTE:
- - cvt_8(p, m);
- + if (cvt_8(p, m) == -1)
- + goto out;
- return 1;
- case FILE_SHORT:
- - cvt_16(p, m);
- + if (cvt_16(p, m) == -1)
- + goto out;
- return 1;
- case FILE_LONG:
- case FILE_DATE:
- case FILE_LDATE:
- - cvt_32(p, m);
- + if (cvt_32(p, m) == -1)
- + goto out;
- return 1;
- case FILE_QUAD:
- case FILE_QDATE:
- case FILE_QLDATE:
- case FILE_QWDATE:
- - cvt_64(p, m);
- + if (cvt_64(p, m) == -1)
- + goto out;
- return 1;
- case FILE_STRING:
- case FILE_BESTRING16:
- @@ -979,65 +995,78 @@
- }
- case FILE_BESHORT:
- p->h = (short)BE16(p);
- - cvt_16(p, m);
- + if (cvt_16(p, m) == -1)
- + goto out;
- return 1;
- case FILE_BELONG:
- case FILE_BEDATE:
- case FILE_BELDATE:
- p->l = (int32_t)BE32(p);
- - cvt_32(p, m);
- + if (cvt_32(p, m) == -1)
- + goto out;
- return 1;
- case FILE_BEQUAD:
- case FILE_BEQDATE:
- case FILE_BEQLDATE:
- case FILE_BEQWDATE:
- p->q = (uint64_t)BE64(p);
- - cvt_64(p, m);
- + if (cvt_64(p, m) == -1)
- + goto out;
- return 1;
- case FILE_LESHORT:
- p->h = (short)LE16(p);
- - cvt_16(p, m);
- + if (cvt_16(p, m) == -1)
- + goto out;
- return 1;
- case FILE_LELONG:
- case FILE_LEDATE:
- case FILE_LELDATE:
- p->l = (int32_t)LE32(p);
- - cvt_32(p, m);
- + if (cvt_32(p, m) == -1)
- + goto out;
- return 1;
- case FILE_LEQUAD:
- case FILE_LEQDATE:
- case FILE_LEQLDATE:
- case FILE_LEQWDATE:
- p->q = (uint64_t)LE64(p);
- - cvt_64(p, m);
- + if (cvt_64(p, m) == -1)
- + goto out;
- return 1;
- case FILE_MELONG:
- case FILE_MEDATE:
- case FILE_MELDATE:
- p->l = (int32_t)ME32(p);
- - cvt_32(p, m);
- + if (cvt_32(p, m) == -1)
- + goto out;
- return 1;
- case FILE_FLOAT:
- - cvt_float(p, m);
- + if (cvt_float(p, m) == -1)
- + goto out;
- return 1;
- case FILE_BEFLOAT:
- p->l = BE32(p);
- - cvt_float(p, m);
- + if (cvt_float(p, m) == -1)
- + goto out;
- return 1;
- case FILE_LEFLOAT:
- p->l = LE32(p);
- - cvt_float(p, m);
- + if (cvt_float(p, m) == -1)
- + goto out;
- return 1;
- case FILE_DOUBLE:
- - cvt_double(p, m);
- + if (cvt_double(p, m) == -1)
- + goto out;
- return 1;
- case FILE_BEDOUBLE:
- p->q = BE64(p);
- - cvt_double(p, m);
- + if (cvt_double(p, m) == -1)
- + goto out;
- return 1;
- case FILE_LEDOUBLE:
- p->q = LE64(p);
- - cvt_double(p, m);
- + if (cvt_double(p, m) == -1)
- + goto out;
- return 1;
- case FILE_REGEX:
- case FILE_SEARCH:
- @@ -1050,6 +1079,9 @@
- file_magerror(ms, "invalid type %d in mconvert()", m->type);
- return 0;
- }
- +out:
- + file_magerror(ms, "zerodivide in mconvert()");
- + return 0;
- }
-
-
- @@ -1066,6 +1098,12 @@
- mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
- const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
- {
- + if (offset >= nbytes) {
- + file_magerror(ms,
- + "offset in magic %u greater than buffer size %zu",
- + offset, nbytes);
- + return -1;
- + }
- /*
- * Note: FILE_SEARCH and FILE_REGEX do not actually copy
- * anything, but setup pointers into the source
- @@ -1230,6 +1268,8 @@
- if (m->in_op & FILE_OPINDIRECT) {
- const union VALUETYPE *q = CAST(const union VALUETYPE *,
- ((const void *)(s + offset + off)));
- + if (OFFSET_OOB(offset + off, nbytes, sizeof(*q)))
- + return 0;
- switch (cvt_flip(m->in_type, flip)) {
- case FILE_BYTE:
- off = q->b;
|